views:

304

answers:

8

In .NET 3.5, I am using the LinkedList class but I am having the following issue. I want the items of that list to be aware of the previous and next items in the list. In other words, I want the method in the items to be able to do this.Next, this.Previous. Is this possible? Below is an example of what I would like to do.

Day d1 = new Day();
Day d2 = new Day();
LinkedList<Day> days = new LinkedList<Day>();
days.AddLast(d1);
days.AddLast(d2);

// Here is want I would like to do
d1.Next = ...

Thanks!

+1  A: 

According to the MSDN, the LinkedListNode class cannot be inherited.

Michael points out that this blog post from Eric Lippert talks about why many classes in the framework are sealed

phsr
I know that... but if I could it would help me a lot!
Martin
I just assumed since the title asked why, I would supply the answer!
phsr
rofl; I'm so torn about whether that's a great or terrible answer! "Why can't inherit from it?" "Because you can't inherit from it!". So accurate yet so unhelpful
STW
@Yoooder: I gave a source as to why.... :-D
phsr
@phsr: Technically, I think your source only confirms the fact, rather than offering a reason why. Though I guess "Because Microsoft don't want you to" is a valid reason.
stevemegson
Ya but you clearly didn't help the OP ahah
DeusAduro
http://blogs.msdn.com/ericlippert/archive/2004/01/22/61803.aspx explains why most framework classes are sealed. There actually are good reasons.
Michael
A: 
Day d1 = new Day();
Day d2 = new Day();
LinkedList<Day> days = new LinkedList<Day>();
// Day's instance doesn't have Next. Its the LinkedListNode that should be used.
LinkedListNode<Day> d1Node = days.AddLast(d1); 
days.AddLast(d2);
shahkalpesh
-1. `LinkedListNode<T>.Next` is read-only. You cannot assign to it.
dtb
@dtb: I am sorry. I just took the code from OP's question and corrected the lines which I thought were wrong. I didn't look into whether one can assign to the Next property.
shahkalpesh
+11  A: 

First, LinkedListNode is sealed so it can not be inherited.

Secondly, LinkedListNode does contain properties Previous and Next that refer to the previous and next nodes in the LinkedList that a given instance of LinkedListNode came from.

Lastly, to use AddLast correctly, you must do the following:

Day d1 = new Day();
Day d2 = new Day();
LinkedList<Day> days = new LinkedList<Day>();
LinkedListNode<Day> node1 = days.AddLast(d1);
LinkedListNode<Day> node2 = days.AddLast(d2);

// now node1.Next refers to node containing d2
// and node2.Previous referes to node containing d1
Jason
+2  A: 

You're using it wrong.

The .AddLast(T) method returns a linked list node. This points to your day and has the prev and next functions you are looking for.

Spence
A: 

LinkedListNode is a sealed class so it cannot be inherited. We get so spoiled by IEnumerable that we lose sight of the actual data structures we're using. It's still a linked list, so you can treat it like one:

LinkedListNode<Day> node = days.First();
while (node != null)
{
    Day day = node.Value;

    // do stuff here...

    node = node.Next();
}
AndyM
-1 Doing this you will skip the last node as "days.Last" refers to a valid node. The while loop should be "while (node != null)" to get all of the nodes
Grant Peters
Thanks for the correction, but a mistake in the loop doesn't change the fundamental answer: traverse the nodes as you would a doubly-linked list to solve the problem.
AndyM
A: 

Why not just use the nodes directly to begin with...

LinkedListNode<Day> d1 = new LinkedListNode<Day>(new Day());
LinkedListNode<Day> d2 = new LinkedListNode<Day>(new Day());
LinkedList<Day> days = new LinkedList<Day>();
days.AddLast(d1); 
days.AddLast(d2);

// Now you can read the node directly
d1.Next...

// If you need to place it somewhere other than at the end (like say you want d2 before d1,
// but d1 is already in the list) use 'AddBefore' and 'AddAfter' eg:
days.AddLast(d2);
days.AddBefore(d2, d1);
Grant Peters
Oh, should also mention, you now just access "Day" through the 'Value' property of d1/d2
Grant Peters
-1. `LinkedListNode<T>.Next` is read-only. You cannot assign to it.
dtb
Oh, didn't realise that, but you can set it via the AddBefore and AddAfter functions
Grant Peters
+2  A: 

Eric Lippert explains why most framework classes are sealed in this blog post.

Michael
A: 

The only way I can think to make a generic T aware of its siblings is to implement your own data structure.

public interface ILinkedListNode
{
    ILinkedListNode Next { get; set; }
    ILinkedListNode Previous { get; set; }
}

public class LinkedList<T> where T : ILinkedListNode 
{
    /*.... methods here ...*/
}

public class Node : ILinkedListNode
{
    public Node Next { get; set; }

    public Node Previous { get; set; }

    ILinkedListNode ILinkedListNode.Next
    {
        get { return this.Next; }
        set { this.Next = (Node)value; }
    }

    ILinkedListNode ILinkedListNode.Previous
    {
        get { return this.Previous; }
        set { this.Previous = (Node)value; }
    }
}
Dave