using System;
using System.Collections;
using System.Collections.Generic;

namespace StructScript
{
public class LinkedListScript<T> : ICollection<T>
{
//表头
public LinkedListNode<T> mHead = null;
//表尾
public LinkedListNode<T> mLast = null;
private int mCount = 0;
public LinkedListScript() { }

public LinkedListScript(IEnumerable<T> collection)
{
if (collection == null)
{
throw new ArgumentNullException();
}
foreach (T item in collection)
{
AddLast(item);
}
}

public LinkedListNode<T> First
{
get
{
return mHead;
}
}

public LinkedListNode<T> Last
{
get
{
return mLast;
}
}

public LinkedListNode<T> AddAfter(LinkedListNode<T> node, T value)
{
if (node == null)
{
throw new ArgumentNullException();
}
LinkedListNode<T> newNode = new LinkedListNode<T>(node.list, value);
InsertAfterNode(node, newNode);
return newNode;
}

public LinkedListNode<T> AddBefore(LinkedListNode<T> node, T value)
{
if (node == null)
{
throw new ArgumentNullException();
}
LinkedListNode<T> newNode = new LinkedListNode<T>(node.list, value);
InsertBeforeNode(node, newNode);
return newNode;
}

public void AddAfter(LinkedListNode<T> node, LinkedListNode<T> newNode)
{
if (node == null || newNode == null)
{
throw new ArgumentNullException();
}
newNode.list = node.list;
InsertAfterNode(node, newNode);
}

public void AddBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
{
if (node == null || newNode == null)
{
throw new ArgumentNullException();
}
if (Contains(newNode.Item))
{
throw new InvalidOperationException();
}
newNode.list = node.list;
InsertBeforeNode(node, newNode);
}

public LinkedListNode<T> AddFirst(T value)
{
LinkedListNode<T> node = new LinkedListNode<T>(this, value);
AddFirst(node);
return node;
}

public LinkedListNode<T> AddLast(T value)
{
LinkedListNode<T> node = new LinkedListNode<T>(this, value);
AddLast(node);
return node;
}

public void AddFirst(LinkedListNode<T> node)
{
if (node == null)
{
throw new ArgumentNullException();
}
if (mHead == null)
{
InsertEmptyLinkedList(node);
}
else
{
InsertBeforeNode(mHead, node);
}
}

public void AddLast(LinkedListNode<T> node)
{
if (node == null)
{
throw new ArgumentNullException();
}
if (mLast == null)
{
InsertEmptyLinkedList(node);
}
else
{
InsertAfterNode(mLast, node);
}
}

public void InsertEmptyLinkedList(LinkedListNode<T> node)
{
node.next = null;
node.prev = null;
//把新增节点赋值为最新的Head, Last节点
mHead = node;
mLast = node;
mCount++;
}

public void InsertAfterNode(LinkedListNode<T> node, LinkedListNode<T> newNode)
{
if (node.next == null)
{
newNode.next = null;
//把新增节点的prev指向之前的Last节点
newNode.prev = mLast;
//把之前的Last节点的next指向新增节点
mLast.next = newNode;
//把新增节点赋值为最新的Last节点
mLast = newNode;
mCount++;
}
else
{
//把新增节点的next指向之前的node节点的next
newNode.next = node.next;
//把新增节点的prev指向之前的node节点
newNode.prev = node;
//把之前的node节点的next的prev指向新增节点
node.next.prev = newNode;
//把之前的node节点的next指向新增节点
node.next = newNode;
mCount++;
}
}

public void InsertBeforeNode(LinkedListNode<T> node, LinkedListNode<T> newNode)
{
if (node.prev == null)
{
//把新增节点的next指向之前的Head节点
newNode.next = mHead;
newNode.prev = null;
//把之前的Head节点的prev指向新增节点
mHead.prev = newNode;
//把新增节点赋值为最新的Head节点
mHead = newNode;
mCount++;
}
else
{
//把新增节点的next指向之前的node节点
newNode.next = node;
//把新增节点的prev指向之前的node节点的prev
newNode.prev = node.prev;
//把之前的node节点的prev的next指向新增节点
node.prev.next = newNode;
//把之前的node节点的prev指向新增节点
node.prev = newNode;
mCount++;
}
}

public LinkedListNode<T> Find(T value)
{
if (value == null)
{
return null;
}
LinkedListNode<T> node = mHead;
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
if (node != null)
{
do
{
if (comparer.Equals(node.Item, value))
{
return node;
}
node = node.next;
} while (node != null);
}
return null;
}

public LinkedListNode<T> FindLast(T value)
{
if (value == null)
{
return null;
}
LinkedListNode<T> node = mLast;
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
if (node != null)
{
do
{
if (comparer.Equals(node.Item, value))
{
return node;
}
node = node.prev;
} while (node != null);
}
return null;
}

public int Count
{
get
{
return mCount;
}
}

public void Add(T item)
{
AddLast(item);
}

public void Clear()
{
LinkedListNode<T> node = mHead;
while (node != null)
{
LinkedListNode<T> node1 = node;
node1.Clear();
node1.Item = default(T);
//当next == list.mLast时,node.Next返回null,跳出循环
node = node.Next;
}
mHead = null;
mLast = null;
mCount = 0;
}

public bool Contains(T item)
{
return Find(item) != null;
}

public void CopyTo(T[] array, int arrayIndex)
{
LinkedListNode<T> node = mHead;
while (node != null)
{
array[arrayIndex] = node.Item;
node = node.next;
arrayIndex++;
}
}

public bool Remove(T item)
{
if (item == null)
{
throw new ArgumentNullException();
}
LinkedListNode<T> node = mHead;
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
while (node != null)
{
if (comparer.Equals(node.Item, item))
{
LinkedListNode<T> node1 = node.prev;
LinkedListNode<T> node2 = node.next;
if (node1 != null)
{
node1.next = node2;
}
else
{
mHead = node2;
}
if (node2 != null)
{
node2.prev = node1;
}
else
{
mLast = node1;
}
node.Clear();
mCount--;
return true;
}
node = node.next;
}
return false;
}

public void Remove(LinkedListNode<T> newNode)
{
if (newNode == null)
{
throw new ArgumentNullException();
}
T item = newNode.Item;
LinkedListNode<T> node = mHead;
EqualityComparer<T> comparer = EqualityComparer<T>.Default;
while (node != null)
{
if (comparer.Equals(node.Item, item))
{
LinkedListNode<T> node1 = node.prev;
LinkedListNode<T> node2 = node.next;
if (node1 != null)
{
node1.next = node2;
}
else
{
mHead = node2;
}
if (node2 != null)
{
node2.prev = node1;
}
else
{
mLast = node1;
}
node.Clear();
mCount--;
break;
}
node = node.next;
}
}

public void RemoveFirst()
{
LinkedListNode<T> node = mHead.next;
node.prev = null;
Remove(mHead);
mHead = node;
}

public void RemoveLast()
{
LinkedListNode<T> node = mLast.prev;
node.next = null;
Remove(mLast);
mLast = node;
}

public IEnumerator<T> GetEnumerator()
{
return new Enumerator(this);
}

IEnumerator IEnumerable.GetEnumerator()
{
return new Enumerator(this);
}

public struct Enumerator : IEnumerator<T>
{
private LinkedListScript<T> list;
private LinkedListNode<T> node;
private int index;
private T current;

public Enumerator(LinkedListScript<T> list)
{
this.list = list;
node = list.mHead;
index = 0;
current = default(T);
}

public T Current
{
get
{
if (index <= 0 || index > list.Count)
{
throw new IndexOutOfRangeException();
}
return current;
}
}

object IEnumerator.Current
{
get
{
if (index <= 0 || index > list.Count)
{
throw new IndexOutOfRangeException();
}
return current;
}
}

public void Dispose()
{

}

public bool MoveNext()
{
if (index >= 0 && index < list.Count)
{
if (node != null)
{
current = node.Item;
node = node.next;
index++;
return true;
}
}
return false;
}

public void Reset()
{
index = 0;
current = default(T);
}
}
}

public sealed class LinkedListNode<T>
{
public LinkedListScript<T> list;
public LinkedListNode<T> next;
public LinkedListNode<T> prev;
private T item;

internal LinkedListNode(LinkedListScript<T> list, T value)
{
this.list = list;
item = value;
}

public T Item
{
get { return item; }
set { item = value; }
}

public LinkedListNode<T> Next
{
get { return next == null || next == list.mLast ? null : next; }
}

public void Clear()
{
list = null;
next = null;
prev = null;
}
}
}

IConnection<T>接口实现:

using System.Collections.Generic;

namespace StructScript
{
public interface ICollection<T> : IEnumerable<T>
{
/// <summary>
/// 返回列表中项的总数
/// </summary>
int Count { get; }

/// <summary>
/// 添加一个新的项到列表中
/// </summary>
void Add(T item);

/// <summary>
/// 从列表中清除所有的项
/// </summary>
void Clear();

/// <summary>
/// 返回列表是否包含特定的项
/// </summary>
bool Contains(T item);

/// <summary>
/// 从列表复制到数组中
/// </summary>
void CopyTo(T[] array, int arrayIndex);

/// <summary>
/// 移除特定对象的第一个匹配项
/// </summary>
bool Remove(T item);
}
}

附上,测试用例:

using System;
using System.Text;
using System.Collections.Generic;

namespace StructScript
{
class TestLinkedList
{
public static void Main()
{
// Create the link list.
string[] words =
{ "the", "fox", "jumped", "over", "the", "dog" };
LinkedListScript<string> sentence = new LinkedListScript<string>(words);
Display(sentence, "The linked list values:");
Console.WriteLine("sentence.Contains(\"jumped\") = {0}", sentence.Contains("jumped"));

// Add the word 'today' to the beginning of the linked list.
sentence.AddFirst("today");
Display(sentence, "Test 1: Add 'today' to beginning of the list:");

// Move the first node to be the last node.
LinkedListNode<string> mark1 = sentence.First;
sentence.RemoveFirst();
sentence.AddLast(mark1);
Display(sentence, "Test 2: Move first node to be last node:");

// Change the last node be 'yesterday'.
sentence.RemoveLast();
sentence.AddLast("yesterday");
Display(sentence, "Test 3: Change the last node to 'yesterday':");

// Move the last node to be the first node.
mark1 = sentence.Last;
sentence.RemoveLast();
sentence.AddFirst(mark1);
Display(sentence, "Test 4: Move last node to be first node:");


// Indicate, by using parentheisis, the last occurence of 'the'.
sentence.RemoveFirst();
LinkedListNode<string> current = sentence.FindLast("the");
IndicateNode(current, "Test 5: Indicate last occurence of 'the':");

// Add 'lazy' and 'old' after 'the' (the LinkedListNode named current).
sentence.AddAfter(current, "old");
sentence.AddAfter(current, "lazy");
IndicateNode(current, "Test 6: Add 'lazy' and 'old' after 'the':");

// Indicate 'fox' node.
current = sentence.Find("fox");
IndicateNode(current, "Test 7: Indicate the 'fox' node:");

// Add 'quick' and 'brown' before 'fox':
sentence.AddBefore(current, "quick");
sentence.AddBefore(current, "brown");
IndicateNode(current, "Test 8: Add 'quick' and 'brown' before 'fox':");

// Keep a reference to the current node, 'fox',
// and to the previous node in the list. Indicate the 'dog' node.
mark1 = current;
LinkedListNode<string> mark2 = current.prev;
current = sentence.Find("dog");
IndicateNode(current, "Test 9: Indicate the 'dog' node:");

// The AddBefore method throws an InvalidOperationException
// if you try to add a node that already belongs to a list.
//Console.WriteLine("Test 10: Throw exception by adding node (fox) already in the list:");
//try
//{
// sentence.AddBefore(current, mark1);
//}
//catch (InvalidOperationException ex)
//{
// Console.WriteLine("Exception message: {0}", ex.Message);
//}
//Console.WriteLine();

// Remove the node referred to by mark1, and then add it
// before the node referred to by current.
// Indicate the node referred to by current.
sentence.Remove(mark1);
sentence.AddBefore(current, mark1);
IndicateNode(current, "Test 11: Move a referenced node (fox) before the current node (dog):");

// Remove the node referred to by current.
sentence.Remove(current);
IndicateNode(current, "Test 12: Remove current node (dog) and attempt to indicate it:");

// Add the node after the node referred to by mark2.
sentence.AddAfter(mark2, current);
IndicateNode(current, "Test 13: Add node removed in test 11 after a referenced node (brown):");

// The Remove method finds and removes the
// first node that that has the specified value.
sentence.Remove("old");
Display(sentence, "Test 14: Remove node that has the value 'old':");

// When the linked list is cast to ICollection(Of String),
// the Add method adds a node to the end of the list.
sentence.RemoveLast();
ICollection<string> icoll = sentence;
icoll.Add("rhinoceros");
Display(sentence, "Test 15: Remove last node, cast to ICollection, and add 'rhinoceros':");

Console.WriteLine("Test 16: Copy the list to an array:");
// Create an array with the same number of
// elements as the inked list.
string[] sArray = new string[sentence.Count];
sentence.CopyTo(sArray, 0);

foreach (string s in sArray)
{
Console.WriteLine(s);
}

// Release all the nodes.
sentence.Clear();

Console.WriteLine();
Console.WriteLine("Test 17: Clear linked list. Contains 'jumped' = {0}",
sentence.Contains("jumped"));

Console.ReadLine();
}

private static void Display(LinkedListScript<string> words, string test)
{
Console.WriteLine(test);
foreach (string word in words)
{
Console.Write(word + " ");
}
Console.WriteLine();
Console.WriteLine();
}

private static void IndicateNode(LinkedListNode<string> node, string test)
{
Console.WriteLine(test);
if (node.list == null)
{
Console.WriteLine("Node '{0}' is not in the list.\n",
node.Item);
return;
}

StringBuilder result = new StringBuilder("(" + node.Item + ")");
LinkedListNode<string> nodeP = node.prev;

while (nodeP != null)
{
result.Insert(0, nodeP.Item + " ");
nodeP = nodeP.prev;
}

node = node.next;
while (node != null)
{
result.Append(" " + node.Item);
node = node.next;
}

Console.WriteLine(result);
Console.WriteLine();
}
}
}