之前我们学习过对象初始化语法,现在我们看一下集合初始化语法:这种语法特性,让你可以用与填充基础数组类似的语法,来填充ArrayList或List<Y>等容器。说明,只能支持Add()方法的类使用集合初始化语法,这是ICollection<T>或ICollection接口决定的。如建立一个point集合类,可以如下表示:List<Point> mylit = new List<Point>{ new point{x=1,y=1}, new point{x=2,y=2}, ...};这种语法的好处是减少键盘输入,但是坏处则是影响可读性。此命名空间下,包括几种泛型类。List<T>,使用最广,用以动态调整的类型。Stack<T>,栈,后进先出的数据集合,包含push和pop方法,分别比欧式进栈和出栈。Queue<T>,队列,先进先出的数据集合,包括Dequeue和Enqueue方法,分别表示在移除开始处对象(并返回)和在队列末尾添加一个对象,除此之外,还有Peek方法,返回队列开始处对象,但并不移除。SortedSet<T>,这个类中的项是自动排序的,在插入和移除之后,也能自动排序,因此该类十分有用。
四、创建自定义的泛型方法/泛型结构和类。
传统方法,交换两个整数:Swap(ref int a, ref int b){ int temp; temp = a; a = b; b = temp;}如果我们继续要交换两个Person对象,则我们必须编写一个swap的新版本:Swap(refPersona, refPersonb){Persontemp; temp = a; a = b; b = temp;}如果需要交换其他的数据,则需要定义更多的方法,这就会给维护带来麻烦,如果想要有单一的方法,我们需要创建操作Object类型的方法,但这样会导致装箱、拆箱,类型安全,显示转换等问题。如果你要创建的方法重载只是输入参数不同,可以使用泛型。方法如下:Swap<T>(ref T a, ref T b){T temp; temp = a; a = b; b = temp;}我们还可以创建泛型类或结构:public class Point<T>{}其中,我们可以是一个双精度的point也可以是一个int的point。1、default(T),和泛型一块儿使用的时候,它表示一个类型参数的默认值。这非常有用,因为一个泛型类型预先并不知道实际的真为辅,因此无法安全的假设默认值是什么。默认值如下:数值的默认值为0;引用类型的默认值是null;一个结构的字段被设为0(值类型)或null(引用类型)。2、泛型基类,泛型类可以作为其他类的基类,它可以定义许多虚方法和抽象方法。但是要做到这些,泛型类需要遵循一些守则:首先,如果一个非泛型类型扩展了一个泛型类,派生类必须指定一个类型参数。public class B:A<string>{}.其中A类为我们自定义的泛型类。其次,如果泛型基类定义了泛型虚方法或抽象方法,派生类型必须使用指定类型参数重写泛型方法。最后,如果派生类型也是泛型,则它能够(可选的)重用类型占位符。不过要注意派生类必须遵照基类中的任何约束。
五,类型参数的约束
如本节描述,任何泛型都必须至少有一个类型参数,并在与泛型类型或参数交互时指定该类型参数,这可以使我们构建类型安全的代码。.net平台使用where关键字可以得到更加具体的类型参数信息。下面几种约束表示如下:where T:struct,该类型参数<T>必须在其继承链中包含System.ValueType值类型,即必须为结构。where T : class,和上面相反,不能包含值类型,必须为引用类型。where T : new(),该类型参数<T>必须包含一个默认的构造函数,因为无法预知子定义构造函数格式,所以如果泛型类型必须创建一个类型参数的实例,这将是非常有用的。注意,在有多个约束的时候,此约束必须列在末尾。where T : NameOfBaseClass,该类型参数<T>必须派生于NameOfBaseClass指定的类。where T : NameOfInterface,同上,必须派生于指定接口,多个接口必须用逗号隔开。例如,如果要指定泛型智能操作结构,可以这样:Swap<T>(ref T a, ref T b) where T : struct {....}。以这种方式约束了Swap方法就不能再对其他如string对象进行交换了,因为string是引用类型。