泛型

泛型可以说是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 框架中,泛型类比比皆是,正式由于他们的存在,强化了代码的通用性以及安全性,减少了使用其他方式创建类似的类型时,出现耗损资源的装箱、拆箱行为,泛型还有很多其他的用途,吾在这里抛砖引玉了。

 

谢谢您的观看,最后祝您身体健康。

posted @ 2016-05-12 10:26  GardenSinner  阅读(142)  评论(0)    收藏  举报