a06e
a06e

Reputation: 20774

How is the interaction between LinkedList<T> and LinkedListNode<T> implemented in C#?

First, let's define a node:

LinkedListNode<int> node = new LinkedListNode<int>(43);

You'll notice that the properties node.List, node.Next and node.Previous are all get only. Now let's add the node to a LinkedList:

LinkedList<int> linkedlist = new LinkedList<int>();
linkedlist.AddFirst(node);

At this point, the property node.List will have change to contain a reference to linkedlist. Similarly, if other nodes are added to the LinkedList, the Next and Previous properties will be updated to reflect the structure of the linked list, even though these properties do not expose a public set accessor.

How is this behavior implemented?

I know how to do it using internal, but is there a better way? For example, suppose I have a single assembly that contains many types, not just LinkedList and LinkedListNode. By making the setters for the node properties List, Previous and Next, I am exposing these setters to the whole assembly, which is undesired.

Upvotes: 0

Views: 1638

Answers (3)

Mike Zboray
Mike Zboray

Reputation: 40828

Jason is correct. I had a look at the source and LinkedListNode<T> has internal backing fields.

One way to do this is with nested classes. I don't know if this qualifies as a "better" way, but it does avoid internal setters/fields. I've left out some of the implementation, so you can see an outline of the structure:

public class Node<T>
{
  private List list;
  private Node<T> prev, next;

  public List List { get { return list; } }
  // other accessors.

  public abstract class List
  {
    Node<T> head;

    internal List() { }

    public AddFirst(Node<T> node)
    {
        // node adding logic.
        node.list = this;       
    }

    // implementation elided for brevity
  }

}

public class MyLinkedList<T> : Node<T>.List { }

Now you can declare a MyLinkedList and add nodes to it, but there are no internal accessors on Node<T>.

Upvotes: 1

jason
jason

Reputation: 241701

How is this behavior implemented?

Without looking at the source, I would guess the setters or backing fields for those properties are marked internal and therefore accessible from LinkedList<T> since they both sit in the same assembly.

but is there a better way?

Not really. Let me elaborate. There are other options.

  1. You could make LinkedListNode<T> an inner class defined in LinkedList<T>. That's an option, but it's burdensome on callers.

  2. You could carve LinkedList<T> and LinkedListNode<T> into their own assembly. That's obviously a burden on users and could quickly degrade into a maintenance debacle.

I characterize both of these as not being better solutions.

Upvotes: 3

Blorgbeard
Blorgbeard

Reputation: 103507

I checked with ILSpy, the read-only properties are backed by internal fields.

internal LinkedListNode<T> next;

public LinkedListNode<T> Next {
    get {
        if (this.next != null && this.next != this.list.head) {
            return this.next;
        }
        return null;
    }
}

As for how to do it differently, and a discussion of whether you'd want to, see this question and its answers.

Upvotes: 1

Related Questions