实现了IEnumerable接口的集合才可以使用foreach
如何进行foreach是通过IENumerable下的GetEnumerable方法来实现的。
这个方法需要一个IEnumerator对象
这个对象的这些方法就决定了怎么样去遍历你定义的集合
如下图是自己定义的LinkedList需要自己去实现下面这个方法。
I
IEnumerator IEnumerable.GetEnumerator()
{
return new ListEnum(this);
}
这个对象我们可以实现IEnumerator接口,然后实现方法就可以了。
public struct ListEnum : IEnumerator, IEnumerator<T>
{
private LinkedList<T> list;
int posistion;
//当前值,只读
object IEnumerator.Current
{
get
{
try
{
return list.FindByIndex(posistion).item;
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
public T Current
{
get
{
try
{
var temp = list.FindByIndex(posistion).item;
return list.FindByIndex(posistion).item;
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
//构造将你的集合拿过来
public ListEnum(LinkedList<T> list)
{
posistion = -1;
this.list = list;
}
//每次遍历时做的事,以及何时停止遍历
public bool MoveNext()
{
posistion++;
return posistion<=list.Count;
}
public void Reset()
{
posistion = -1;
}
public void Dispose()
{
}
}
我们将链表从头到尾的遍历一遍。
完整代码如下
using Google.ProtocolBuffers;
using System;
using System.Collections;
using System.Collections.Generic;
using System.Text;
namespace GrapeCity.Winston.LinkedList
{
public class LinkedList<T> : object, IList<T>
{
internal LinkedListNode<T> Head;
private EqualityComparer<T> compare = EqualityComparer<T>.Default;
int Count { get; set; }
int ICollection<T>.Count
{
get
{
return Count;
}
}
//index
public T this[int index] { get => throw new NotImplementedException(); set => throw new NotImplementedException(); }
public bool IsReadOnly
{
get
{
return true;
}
}
public LinkedList()
{
Count = 0;
}
public LinkedList(IEnumerable<T> collection)
{
if (collection == null)
{
throw new ArgumentNullException("collection");
}
foreach (T item in collection)
{
}
}
public LinkedListNode<T> GetHead()
{
return this.Head;
}
public void Add(T item)
{
if (Head == null)
{
Head = new LinkedListNode<T>(item);
}
else
{
LinkedListNode<T> lastNode = FindLastNode();
InternalInsertNodeAfter(lastNode, new LinkedListNode<T>(item));
}
}
//往节点后添加一个新节点
public void AddAfter(LinkedListNode<T> node, T value)
{
LinkedListNode<T> result = new LinkedListNode<T>(value);
InternalInsertNodeAfter(node.Next, result);
}
//把newNode插入到node前面
private void InternalInsertNodeBefore(LinkedListNode<T> node, LinkedListNode<T> newNode)
{
newNode.Next = node;
newNode.Prev = node.Prev;
node.Prev.Next = newNode;
node.Prev = newNode;
Count++;
}
//把newNode插入到node后面
private void InternalInsertNodeAfter(LinkedListNode<T> node, LinkedListNode<T> newNode)
{
newNode.Prev = node;
newNode.Next = null;
node.Next = newNode;
Count++;
}
public LinkedListNode<T> FindLastNode()
{
LinkedListNode<T> index = Head;
while (index.Next != null)
{
index = index.Next;
}
return index;
}
//根据item的值来查找到多个节点
public LinkedListNode<T> Find(T value)
{
LinkedListNode<T> index = Head;
while (index != null && value != null)
{
if (compare.Equals(index.item, value))
{
return index;
}
index = index.Next;
}
return null;
}
public LinkedListNode<T> FindByIndex(int listIndex)
{
var temp = this.GetHead();
for (int index = 0; index <= listIndex && temp != null; index++)
{
if (index == listIndex)
{
return temp;
}
temp = temp.Next;
}
return null;
}
public void Clear()
{
LinkedListNode<T> current = Head;
while (current != null)
{
var temp = current;
current = current.Next;
temp.Invalidate();
}
Head = null;
Count = 0;
}
public bool Contains(T item)
{
throw new NotImplementedException();
}
public void CopyTo(T[] array, int arrayIndex)
{
throw new NotImplementedException();
}
public int IndexOf(T item)
{
throw new NotImplementedException();
}
//根据下标添加
public void Insert(int index, T item)
{
var findNode = FindByIndex(index);
InternalInsertNodeBefore(findNode, new LinkedListNode<T>(item));
}
public bool Remove(T item)
{
LinkedListNode<T> node = Find(item);
while (node != null)
{
RemoveFirst(node);
}
return true;
}
public void RemoveFirst(T item)
{
var node = Find(item);
RemoveFirst(node);
}
public void RemoveFirst(LinkedListNode<T> node)
{
//删除头结点
if (node == Head)
{
Head = Head.Next;
}
//删除尾节点
else if (node.Next == null)
{
node.Prev.Next = null;
node.Prev = null;
}
//删除中间节点
else
{
node.Next.Prev = node.Prev;
node.Prev.Next = node.Next;
}
node.Invalidate();
Count--;
}
public void RemoveAt(int index)
{
var removeNode = FindByIndex(index);
RemoveFirst(removeNode);
}
//需要Ienumerator对象来定义foreach遍历的规则
public IEnumerator<T> GetEnumerator()
{
return new ListEnum(this);
}
IEnumerator IEnumerable.GetEnumerator()
{
return new ListEnum(this);
}
public class LinkedListNode<T>
{
internal LinkedListNode<T> Next;
internal LinkedListNode<T> Prev;
internal T item;
public LinkedListNode(T value)
{
this.item = value;
}
public override string ToString()
{
return $"{this.item}";
}
internal void Invalidate()
{
Next = null;
Prev = null;
}
}
//TODO 用于遍历,记得删除
public void WatchLinkedList<T>()
{
StringBuilder str = new StringBuilder();
var index = this.GetHead();
while (index != null)
{
str.Append(index.ToString());
str.Append(" ");
index = index.Next;
}
Console.WriteLine(str);
}
public struct ListEnum : IEnumerator, IEnumerator<T>
{
private LinkedList<T> list;
int posistion;
object IEnumerator.Current
{
get
{
try
{
return list.FindByIndex(posistion).item;
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
public T Current
{
get
{
try
{
var temp = list.FindByIndex(posistion).item;
return list.FindByIndex(posistion).item;
}
catch (IndexOutOfRangeException)
{
throw new InvalidOperationException();
}
}
}
public ListEnum(LinkedList<T> list)
{
posistion = -1;
this.list = list;
}
public bool MoveNext()
{
posistion++;
return posistion<=list.Count;
}
public void Reset()
{
posistion = -1;
}
public void Dispose()
{
}
}
}
}
这样我们就实现了一个非常简单的链表。