在前面的文章中,向大家展示了C#语言链表的最简单实现.
我们知道在C#语言中有一个循环是其他C风格的语言中没有(最新的java也有了),那就是foreach循环,这种循环是从basic语言中学来的.利用这种循环(使用了iterator模式)我们可以在不知道集合长度的情况下,来对集合中的元素进行遍历,实在是很方便.
可是前面我们作的链表,大家如果使用过的话,会发现它根本就不能使用foreach进行遍历.
那么我们如何才能让这个类支持foreach呢?其实很简单,只要让我们的链表类继承自IEnumerable接口,并对该接口中的GetEnumerator()方法加以实现就可以了.
大家请看下面的代码,是前面我们实现的链表类的加强版,首选让CSArrayList 类继承自 IEnumerable接口,最下边红色的字,是对GetEnumerator()方法加以实现.
using
System;
using
System.Collections.Generic;
using
System.Text;
using
System.Collections;
namespace
链表加强版_可以使用foreach语句进遍历_
{
///<summary>
///
用于表示链表的一个结点
///</summary>
public class CSArrayListNode
{
private object element;
///<summary>
///
当前结点中的元素值
///</summary>
public object Element
{
get { return element; }
set { element = value; }
}
private CSArrayListNode nextNode;
///<summary>
///
该结结点的下一个结点的引用
///</summary>
public CSArrayListNode NextNode
{
get { return nextNode; }
set { nextNode = value; }
}
}
///<summary>
///
用于表示链表
///</summary>
public class CSArrayList:IEnumerable
{
CSArrayListNode firstNode;
int count; bool isReadOnly = false;
///<summary>
///
获取 CSArrayList 中实际包含的元素数。
///</summary>
public int Count
{
get
{
return this.count;
}
}
///<summary>
///
将对象添加到 CSArrayList 的结尾处。
///</summary>
///<param name="Item">
要添加到 CSArrayList 的末尾处的 Object。该值可以为 空引用.
</param>
public void Add(object Item)
{
//
第一次加入元素
if (this.firstNode == null)
{
this.firstNode = new CSArrayListNode();
this.firstNode.Element = Item;
}
//
非第一次加入元素
else
{
CSArrayListNode tmpnode = this.firstNode;
//
通过循环找到最后一个结点
while (true)
{
//
如果该结点为空,则将新值插入该链表
if (tmpnode.NextNode == null)
{
tmpnode.NextNode = new CSArrayListNode();
tmpnode.NextNode.Element = Item;
break;
}
tmpnode = tmpnode.NextNode;
}
}
//
链表长度增加1
this.count++;
}
///<summary>
///
从 CSArrayList 中移除所有元素。
///</summary>
public void Clear()
{
//
最好将所有结点清空
this.firstNode = null;
}
///<summary>
///
确定某元素是否在 CSArrayList 中。
///</summary>
///<param name="item">
要在 ArrayList 中查找的 Object。该值可以为 空引用
</param>
///<returns>
如果在 CSArrayList 中找到 item,则为 true;否则为 false。
</returns>
public bool Contains(object item)
{
CSArrayListNode tmpnode = this.firstNode;
while (true)
{
if (tmpnode == null)
{
return false;
}
if (tmpnode.Element.Equals(item))
{
return true;
}
tmpnode = tmpnode.NextNode;
}
}
///<summary>
///
搜索指定的 Object,并返回整个 ArrayList 中第一个匹配项的从零开始的索引。
///</summary>
///<param name="value">
要在 ArrayList 中查找的 Object。
</param>
///<returns>
如果在整个 ArrayList 中找到 value 的第一个匹配项,则为该项的从零开始的索引;否则为 -1。
</returns>
public int IndexOf(object value)
{
CSArrayListNode tmpnode = this.firstNode;
int index = 0;
while (true)
{
//
如果找到最后一个还找不到,则返回-1
if (tmpnode == null)
{
return -1;
}
//
否则返回索引号
if (tmpnode.Element.Equals(value))
{
return index;
}
tmpnode = tmpnode.NextNode;
index++;
}
}
///<summary>
///
将元素插入 ArrayList 的指定索引处。
///</summary>
///<param name="index">
从零开始的索引,应在该位置插入 value。
</param>
///<param name="value">
要插入的 Object。
</param>
public void Insert(int index, object value)
{
//
如果索引号大于该链表的长度,则不作为
if (index > this.count)
{
return;
}
//
如果索引号是0,则直接将该值插入第一个结点
if (index == 0)
{
CSArrayListNode node = new CSArrayListNode();
node.Element = value;
node.NextNode = this.firstNode;
this.firstNode = node;
this.count++;
return;
}
CSArrayListNode tmpnode = this.firstNode;
int index1 = 0;
while (true)
{
if (tmpnode == null)
{
return;
}
//
插入新值,这里要注意结点是如何交换的
//C#
的类名就是引用,这一点类似于C++中的指针
if (index == (index1 + 1))
{
CSArrayListNode node = new CSArrayListNode();
node.Element = value;
node.NextNode = tmpnode.NextNode;
tmpnode.NextNode = node;
this.count++;
return;
}
tmpnode = tmpnode.NextNode;
index1++;
}
}
///<summary>
///
从 ArrayList 中移除特定对象的第一个匹配项。
///</summary>
///<param name="value">
要从 ArrayList 移除的 Object。
</param>
public void Remove(object value)
{
if (this.firstNode.Element.Equals(value))
{
this.firstNode = this.firstNode.NextNode;
this.count--;
return;
}
int index = 0;
CSArrayListNode tmpnode = this.firstNode;
while (true)
{
if (tmpnode.NextNode == null)
{
return;
}
if (tmpnode.NextNode.Element.Equals(value))
{
tmpnode.NextNode = tmpnode.NextNode.NextNode;
this.count--;
return;
}
tmpnode = tmpnode.NextNode;
index++;
}
}
///<summary>
///
移除 ArrayList 的指定索引处的元素。
///</summary>
///<param name="index">
要移除的元素的从零开始的索引。
</param>
public void RemoveAt(int index)
{
if (index > this.count)
{
return;
}
if (index == 0)
{
this.firstNode = this.firstNode.NextNode;
this.count--;
return;
}
int index1 = 0;
CSArrayListNode tmpnode = this.firstNode;
while (true)
{
if (index1 == (this.count - 1))
{
return;
}
if (index == (index1 + 1))
{
tmpnode.NextNode = tmpnode.NextNode.NextNode;
this.count--;
return;
}
tmpnode = tmpnode.NextNode;
index1++;
}
}
public object this[int index]
{
get
{
if (index > this.count - 1)
{
return null;
}
CSArrayListNode tmpnode = this.firstNode;
for (int i = 0; i < index; i++)
{
tmpnode = tmpnode.NextNode;
}
return tmpnode.Element;
}
set
{
if (index > this.count - 1)
{
return;
}
CSArrayListNode tmpnode = this.firstNode;
for (int i = 0; i < index; i++)
{
tmpnode.NextNode = tmpnode.NextNode;
}
tmpnode.Element = value;
}
}
#region IEnumerable
成员
//
大家这里要注意yield return语句后的this[i]实际上
CSArrayList
类的索引器
public IEnumerator GetEnumerator()
{
for (int i = 0; i < this.count ; i++)
{
yield return this[i];
}
}
#endregion
}
}