泛型
泛型可以说是C#的一大特色,这里讨论一下如何将一个简单的类转化为泛型类型。
1.实现一个简单的一般的链表类
public class LinkListNode { public object value; public LinkListNode Next { get; set; } public LinkListNode Prev { get; set; } public LinkListNode(Object value) { this.value = value; } } public class LinkList:IEnumerable { public LinkListNode First { get; set; } public LinkListNode Last { get; set; } /// <summary> /// 从末尾添加一个节点 /// </summary> /// <param name="node">添加的节点</param> /// <returns></returns> public LinkListNode AddLast(object node) { var newNode = new LinkListNode(node); if (First == null) { First = newNode; Last = First; } else { LinkListNode previous = Last; Last.Next = newNode; Last.Prev = previous; Last = newNode; } return newNode; } public IEnumerator GetEnumerator() { LinkListNode current = First; while (current!=null) { yield return current.value; current = current.Next; } } }
注意此处我们为自定义的类型添加了枚举功能(实现IEnumrable接口即可),该接口只有一个GetEnumerator方法,用于实现自定义的迭代规则。
下面就可以测试一下这个类的使用方法了 class Program
{ public static void Main() { LinkList list = new LinkList(); list.AddLast(2); list.AddLast("6"); list.AddLast(5.7D); list.AddLast(3.2F); list.AddLast(new { name=2,age=23});
//如果将var换做其他的类型,比如int此处则会发生异常 foreach (var item in list) { Console.WriteLine(item); } } }
从代码可以看出,我们添加了任意的类型,运行程序,得到如下的输出,也就是说,我们的这个类可以接收任何类型的数据进行处理,但是,仅仅因为这个遍历,这个类型存在着如下的问题:
(1)发生了太多次的装箱操作。如果string类型和匿名类型,其他的节点加入链表的时候,都会发生装箱操作,这在数据量大的情况下,是很耗费系统资源的。
(2)安全访问性,如注释所写,当我们将推断类型var改为其他的类型(如int)时,如果我们的数据成员不能和该类型匹配(如字符串),就会发生异常,如下所示:

为了提高类型的安全访问性。我们引入了泛型类,将该类修改为泛型版本:
public class LinkListNode<T> { public T value; public LinkListNode<T> Next { get; set; } public LinkListNode<T> Prev { get; set; } public LinkListNode(T value) { this.value = value; } } public class LinkList <T>: IEnumerable<T> { public LinkListNode<T> First { get; set; } public LinkListNode<T> Last { get; set; } /// <summary> /// 从末尾添加一个节点 /// </summary> /// <param name="node">添加的节点</param> /// <returns></returns> public LinkListNode<T> AddLast(T node) { var newNode = new LinkListNode<T>(node); if (First == null) { First = newNode; Last = First; } else { LinkListNode<T> previous = Last; Last.Next = newNode; Last.Prev = previous; Last = newNode; } return newNode; } public IEnumerator<T> GetEnumerator() { LinkListNode<T> current = First; while (current != null) { yield return current.value; current = current.Next; } }
//注意实现 IEnumerator IEnumerable.GetEnumerator() { return GetEnumerator(); } }
注意此处的枚举接口IEnumrable<T>,他是继承IEnumerable接口的,所以我们还需实现IEnumerable的GetEumerator方法.
这时候,我们使用新的泛型类时,就不能添加不同类型的节点了,该类型必须和我们指定的类型一致,如果我们违反了这个规则,编译器也能在编译过程中提示我们这种错误,从而提高了代码的安全性。
public static void Main() { LinkList<int> list = new LinkList<int>(); list.AddLast(2); // list.AddLast("6"); // list.AddLast(5.7D); // list.AddLast(3.2F); // list.AddLast(new { name = 2, age = 23 }); foreach (var item in list) { Console.WriteLine(item); } }
例如我们想添加一个非int类型的节点进入链表中,则会出现如下的提示:

在.NET 框架中,泛型类比比皆是,正式由于他们的存在,强化了代码的通用性以及安全性,减少了使用其他方式创建类似的类型时,出现耗损资源的装箱、拆箱行为,泛型还有很多其他的用途,吾在这里抛砖引玉了。
谢谢您的观看,最后祝您身体健康。
欲买桂花同载酒,只可惜故人……何日再见呐…

浙公网安备 33010602011771号