Reputation: 20774
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
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
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.
You could make LinkedListNode<T>
an inner class defined in LinkedList<T>
. That's an option, but it's burdensome on callers.
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
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