.NET漫游指南-008-泛型,装箱,泛型委托

来源:互联网 发布:卫生网络答题 编辑:程序博客网 时间:2024/04/30 13:55

概述

这篇主要讨论,泛型的相关概念,什么是泛型,泛型的形式,为什么要用泛型,泛型与类型的装箱有什么优劣,泛型委托的应用,泛型委托的简化编写等内容的较为仔细的浅谈。

CLR 2.0引入了泛型,泛型将类型参数的概念引入.NET,在这之前C#是通过将类型于基类型Object相互强制转化来完成泛化,这就付出了一定的代价,任何类型向上转化成Object时,如果类型为值类型,将他们添加到列表中时必须将其装箱,检索他们时必须取消装箱,无疑这种处理在循环访问大型集合方案时会降低性能。此外编译时缺少类型检查,因此编译时无法检查数据的安全性,只有在运行时才会报错,增加了编码的风险。

泛型类和泛型方法兼具可重用性,类型安全和效率,泛型通常与集合以及作用于集合的方法一起使用。
泛型委托可以自己定义,也可以使用Microsoft内置的泛型委托如:Action,Function等。内置的泛型委托,满足了对泛型委托要求不高的情况下的快速使用。

下面先讲述泛型集合,泛型类,泛型接口,泛型方法,泛型和数组

下面通过对比ArrayList集合类和List集合类来表现泛型的安全性检查的优势。

    class ArrayListAndList    {        System.Collections.ArrayList arrayList = new System.Collections.ArrayList();        public ArrayListAndList()        {            int i = 0;            arrayList.Add(5);            arrayList.Add(9);            arrayList.Add("异类");            foreach(int item in arrayList)            {                i += item;            }        }    }

上面的代码编译是可以通过的,虽然第三个add中添加了一个string类型的数据,但是编译器并不会进行检查。但是当代码运行到foreach代码时就会报出“System.InvalidCastException”类型的异常,就是类型转化的异常。

 class ArrayListAndList    {        System.Collections.ArrayList arrayList = new System.Collections.ArrayList();        List<int> list = new List<int>();        public ArrayListAndList()        {            int i = 0;            arrayList.Add(5);            arrayList.Add(9);            arrayList.Add("异类");            foreach(int item in arrayList)            {                i += item;            }            int j = 0;            list.Add(5);            list.Add(9);            list.Add("异类");            foreach(var item in list)            {                j += item;            }        }    }

List在编码过程中编译器就会报出error CS1503: Argument 1: cannot convert from ‘string’ to ‘int’的错误。
为什么会ArrayList只有在运行的时候会报错,但是List在编译的时候就会报错。
因为在ArrayList中当添加5,9,异类,时已经把数值进行了封箱,当进行foreach循环时将元素拆箱成int型,当拆到“异类”时,拆箱失败,所以就报出了类型转换失败的原因。
ArrayList相对于List来说更为自由,可以创建异类集合,虽然这种集合是可以被程序接受的,甚至于某些情况下要用到这个特性,但是毕竟埋下了类型转化的隐患。

泛型类封装非特定数据类型的操作,但是要注意防止类的过度泛化,泛化虽然提高了代码的灵活性和重用性,但是过度泛化会降低代码的可读性。无限制参数类型的泛化会产生一定的弊端。

泛型类

参考网址:https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/generics/generic-classes
首先看泛型类,在创建泛型类的时候需要考虑的几点。
1:将哪些类型泛化为类型参数,保持灵活性和可读性的平衡,避免过度泛化。2:对类型参数采用何种约束机制,原则是在保证可以处理必要数据的情况下采用最大程度的约束(约束机制,参见泛型约束的博文)。
3:是否将泛型分解为基类和子类。
4:是实现一个还是多个泛型接口。
开放结构泛型类:Node<T> 封闭结构泛型类:Node<int> 上面讲述的List<int> 就是一个封闭泛型。

关于其继承性

class BaseNode { }class BaseNodeGeneric<T> { }// concrete typeclass NodeConcrete<T> : BaseNode { }//closed constructed typeclass NodeClosed<T> : BaseNodeGeneric<int> { }//open constructed type class NodeOpen<T> : BaseNodeGeneric<T> { }//No errorclass Node1 : BaseNodeGeneric<int> { }//Generates an error//class Node2 : BaseNodeGeneric<T> {}//Generates an error//class Node3 : T {}class BaseNodeMultiple<T, U> { }//No errorclass Node4<T> : BaseNodeMultiple<T, int> { }//No errorclass Node5<T, U> : BaseNodeMultiple<T, U> { }//Generates an error//class Node6<T> : BaseNodeMultiple<T, U> {}

下面代码是演示泛型类的代码
可以看出:为了可以实现foreach中的迭代,泛型基类GenericList实现了IEnumerable泛型接口
基类GenericList的子类SortedLsit,为了使其参数类型T可以使用compare方法,用IComparable泛型接口对参数类型T进行了泛型约束。然后定义了一个类Person,person类也实现了IComparable接口(这样就可以用SortedList类来进行排序了)。

/********************************* * 该文件是为了帮助理解自定义泛型类 * 首先是定义了自定义的泛型类GenericList,继承了必要的泛型接口,作为基类。 * 然后根据基类GenericList派生出子类SortList,并对类型参数做了约束限制 * 同时创建了一个Person的类,并继承了IComparable接口 * ********************************/    class GenericTest    {        #region an generic list        //creat a generic list class         //IEnumerable<T> supports a simple iteration over a collection of a specified type        public class GenericList<T> : System.Collections.Generic.IEnumerable<T>        {            protected Node head;            protected Node current = null;            protected class Node            {                public Node next;                private T data;     //T as a private member datatype                public Node(T t)                {                    next = null;                    data = t;                }                public Node Next                {                    set { next = value; }                    get { return next;  }                }                public T Data                {                    set { data = value; }                    get { return data; }                }            }            public GenericList()            {                head = null;            }            //add Node from the head            public void AddHead(T t)            {                Node newNode = new Node(t);                newNode.next = head;                head = newNode;            }            public System.Collections.Generic.IEnumerator<T> GetEnumerator()            {                Node current = head;                while (current != null)                {                    yield return current.Data;      //yield means the getor is a iterator.                    current = current.next;                }            }            //return an enumerator  that iterates through the collection            System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()            {                 return GetEnumerator();            }        }        #endregion        #region a SortLsit based on generic list        public class SortedList<T>:GenericList<T> where T : System.IComparable<T>        {            //这个是单链的bubble排序,可以参考数据结构中的排序方法讲解            public void BubbleSort()            {                if (head == null || head.next == null)                    return;                bool swapped;                do                {                    Node previous = null;                    Node current = head;                    swapped = false;                    while(current.next != null)                    {                        if (current.Data.CompareTo(current.next.Data) > 0)                        {                            Node temp = current.next;                            current.next = current.next.next;                            temp.next = current;                            if(previous == null)                            {                                head = temp;                            }                            else                            {                                previous.next = temp;                            }                            previous = temp;                            swapped = true;                        }                        else                        {                            previous = current;                            current = current.next;                        }                    }                } while (swapped);            }        }        #endregion    }    public class Person : System.IComparable<Person>    {        string name;        int age;        public Person(string s ,int i)        {            name = s;            age = i;        }        int IComparable<Person>.CompareTo(Person other)        {            return age - other.age;        }        public bool Equals(Person other)        {            return age == other.age;        }        public override string ToString()        {            return name + ":" + age;        }    }

实例化上述类的代码

SortedList<Person> personList = new SortedList<Person>();            string[] names = new string[]            {                "Jonny",                "Kline",                "Martin"            };            int[] ages = new int[]            {                24,                39,                54            };            for(int i = 0; i < 3; i++)            {                personList.AddHead(new Person(names[i], ages[i]));            }            //使用IEnumerable接口中的迭代器和IComparable接口中的比较方法            System.Console.WriteLine("unsort");            foreach(var item in personList)            {                System.Console.WriteLine(item.ToString());            }            //实现类中的排序方法            personList.BubbleSort();            System.Console.WriteLine("sorted");            foreach(var item in personList)            {                System.Console.WriteLine(item.ToString());            }        }    }

上述代码使用自定义的泛型类实现了对person对象的bubble sort,虽然实现了,但是整体的实现还是较为复杂的,可以参考之前写的一篇002-委托中利用泛型委托来实现bubble sort。两篇文章中的实现有共通之处,但是到项目中具体使用哪一种方式,还是要对比考虑的。

原创粉丝点击