C#泛型(二)——创建泛型类

首先介绍一个一般的、非泛型的简化链表类,它可以包含任意类型的对象,以后再把这个类转化为泛型类。

在链表中,一个元素引用下一个元素。所以必须创建一个类,它将对象封装在链表中,并引用下一个对象。类LinkedListNode包含一个属性Value,该属性用构造函数初始化。另外,LinkedListNode类包含对链表中下一个元素和上一个元素的引用,这些元素都可以从属性中访问。

public class LinkedListNode

{

public LinkedListNode(object value)

{

Value = value;

}

public object Value {get; private set; }

public LinkedListNode Next { get; internal set; }

public LinkedListNode Prev { get; internal set; }

}

LinkedList类包含LinkedListNode类型的First和Last属性,它们分别标记了链表的头尾。AddLast()方法在链表尾添加一个新元素。首先创建一个LinkedListNode类型的对象。如果链表是空的,First和Last属性就设置为该新元素;否则,就把新元素添加为链表中的最后一个元素。通过实现GetEnumerator()方法,可以用foreach语句遍历链表。GetEnumerator()方法使用yield语句创建一个枚举器类型。

public class LinkedList: IEnumerable

{

public LinkedListNode First {get; private set; }

public LinkedListNode Last {get; private set; }

public LinkedListNode AddLast(object node)

{

var newNode = new LinkedListNode( node);

if (First == null)

{

First = newNode;

Last = First;

}

else

{

LinkedListNode previous = Last;

Last.Next = newNode;

Last = newNode;

Last.Prev = previous;

}

return newNode;

}

public IEnumerator GetEnumerator()

{

LinkedListNode current = First;

while (current ! = null)

{

yield return current.Value;

current = current.Next;

}

}

}  

注意:yield语句创建一个枚举器的状态机。

现在可以对于任意类型使用LinkedList类了。在下面的代码段中,实例化了一个新LinkedList对象,添加了两个整数类型和一个字符串类型。整数类型要转换为一个对象,所以执行装箱操作,如前面所述。通过foreach语句执行拆箱操作。在foreach语句中,链表中的元素被强制转换为整数,所以对于链表中的第3个元素,会发生一个运行时异常,因为把它强制转换为int时会失败。

var list1 = new LinkedList();

list1. AddLast(2);

list1. AddLast(4);

list1. AddLast("6");

foreach (int i in list1)

{

WriteLine( i);

}

下面创建链表的泛型版本。泛型类的定义与一般类类似,只是要使用泛型类型声明。之后,泛型类型就可以在类中用作一个字段成员,或者方法的参数类型。LinkedListNode类用一个泛型类型T声明。属性Value的类型是T,而不是object。构造函数也变为可以接受T类型的对象。也可以返回和设置泛型类型,所以属性Next和Prev的类型是LinkedListNode<T>。

public class LinkedListNode<T>

{

public LinkedListNode(T value)

{

Value = value;

}

public T Value { get; private set; }

public LinkedListNode<T> Next { get; internal set; }

public LinkedListNode<T> Prev { get; internal set; }

}

下面的代码把LinkedList类也改为泛型类。LinkedList<T>包含LinkedListNode<T>元素。LinkedList中的类型T定义了类型T的属性First和Last。AddLast()方法现在接受类型T的参数,并实例化LinkedListNode<T>类型的对象。

除了IEnumerable接口,还有一个泛型版本IEnumerable<T>。IEnumerable<T>派生自IEnumerable,添加了返回IEnumerator<T>的GetEnumerator()方法,LinkedList<T>实现泛型接口IEnumerable<T>

public class LinkedList< T>: IEnumerable< T>

{

public LinkedListNode<T> First { get; private set; }

public LinkedListNode<T> Last { get; private set; }

public LinkedListNode<T> AddLast( T node) { var newNode = new LinkedListNode< T>( node);

if (First == null)

{

First = newNode;

Last = First;

}

else

{

LinkedListNode<T> previous = Last;

Last.Next = newNode;

Last = newNode;

Last.Prev = previous;

}

return newNode;

}

public IEnumerator<T> GetEnumerator()

{

LinkedListNode<T> current = First;

while (current ! = null)

{

yield return current.Value;

current = current. Next;

}

}

IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();

}

使用泛型LinkedList<T>,可以用int类型实例化它,且无需装箱操作。如果不使用AddLast()方法传递int,就会出现一个编译器错误。使用泛型IEnumerable<T>,foreach语句也是类型安全的,如果foreach语句中的变量不是int,就会出现一个编译器错误。

var list2 = new LinkedList<int>();

list2.AddLast( 1);

list2.AddLast( 3);

list2. AddLast( 5);

foreach (int i in list2)

{

WriteLine(i);

}

同样,可以对于字符串类型使用泛型LinkedList<T>,将字符串传递给AddLast()方法。

var list3 = new LinkedList< string>();

list3.AddLast("2");

list3.AddLast("four");

list3.AddLast("foo");

foreach (string s in list3)

{

WriteLine( s);

}

注意: 每个处理对象类型的类都可以有泛型实现方式。另外,如果类使用了层次结构,泛型就非常有助于消除类型强制转换操作。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

掌控自身命运

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值