tags:

views:

308

answers:

1

I am making a seperate thread here because I believe if I write a comment, the comment won't push the thread to the top and thus there'll be notification for anyone who has written to that thread.

This code was supplied by Micheal Buen at the thread http://stackoverflow.com/questions/410324/writing-text-to-the-middle-of-a-file :

        LinkedList<string> beatles = new LinkedList<string>();

        beatles.AddFirst("John");
        LinkedListNode<string> nextBeatles = beatles.AddAfter(beatles.First, "Paul");
        nextBeatles = beatles.AddAfter(nextBeatles, "George");
        nextBeatles = beatles.AddAfter(nextBeatles, "Ringo");
        nextBeatles = beatles.AddAfter(nextBeatles, "George");
        nextBeatles = beatles.AddAfter(nextBeatles, "Ringo");

        nextBeatles = beatles.AddAfter(nextBeatles, "George");
        nextBeatles = beatles.AddAfter(nextBeatles, "Ringo");

        nextBeatles = beatles.AddAfter(nextBeatles, "George");
        nextBeatles = beatles.AddAfter(nextBeatles, "Ringo");

        nextBeatles = beatles.AddAfter(nextBeatles, "George");
        nextBeatles = beatles.AddAfter(nextBeatles, "Ringo");


        // change the 1 to your 5th line
        LinkedListNode<string> paulsNode = beatles.NodeAt(6);
        LinkedListNode<string> recentHindrance = beatles.AddBefore(paulsNode, "Yoko");
        recentHindrance = beatles.AddBefore(recentHindrance, "Aunt Mimi");
        beatles.AddBefore(recentHindrance, "Father Jim");


        Console.WriteLine("{0}", string.Join("\n", beatles.ToArray()));

        Console.ReadLine();

public static class Helper
{
    public static LinkedListNode<T> NodeAt<T>(this LinkedList<T> l, int index)
    {
        LinkedListNode<T> x = l.First;

        while ((index--) > 0)
        {
                x = x.Next;
            Console.Write(x.Value);
            Thread.Sleep(10000);
        }



        return x;
    }
}

What I am wondering is, what does the extension method achieve?

On first pass, x = x.Next means we are looking at Ringo rather than George, and so on. What exactly is happening under the bonnet and what is the code doing from the point when I call NodeAt(6) onwards? I ask this as it's important to be able to read and understand code without using the stepping through approach as an aid (sometimes at work you will read code in a printed document, for example). Also, why do we count backwards in the loop and why is there a bracket to subtract 1 before entering the loop body?

Thanks

+6  A: 

The extension method only steps through the LinkedList n elements, it initializes x with the first element of the list (l.First) and then in the while, it decrements the index to step forward n times (look x = x.Next;):

Index:  1           2            3            4
     _ _ _ _     _ _ _ _     _ _ _ _ _     _ _ _ _
    | John  |-> | Paul  |-> | George  |-> | Ringo |
     ‾ ‾ ‾ ‾     ‾ ‾ ‾ ‾     ‾ ‾ ‾ ‾ ‾     ‾ ‾ ‾ ‾

So if you call the method with the index 4 (NodeAt(4)), it will get the first item (John), decrement the counter (to 3), step to the next item (Paul), decrement again (2), get the next item (George), decrement (to 1), get the next item (Ringo) and then decrement to 0 and this will exit the while, and return the LinkedList Item, at the 4 position (Ringo).

Additionally you might want to check the ElementAt extension method provided by System.Linq to achieve the same:

var linkedList = new LinkedList<string>(new []{"John", "Paul", "George", "Ringo"});
linkedList.ElementAt(3); // this returns you Ringo, note that 
                         // the index is 0-based!
CMS
Nice ASCII art! +1
Lucas McCoy
Yes, +1 for the picture. But the list actually is double-linked
Henk Holterman
Thanks both, @Henk I drawed it singly-linked because the algorithm traverses the list in only one direction
CMS
Thanks for this explanation of the logic! Seems so basic now, with hindsight. :)
dotnetdev