泛型总结:
泛型定义(什么是泛型):
泛型是具有占位符(类型参数)的类、结构、接口和方法,其中占位符也就是类型参数,可以是一个或多个,在占位符的两边加上尖括号:<T>
泛型使用的各种形式:
类型参数与泛型约束:
类型参数一般使用大写字母T,或者以大写字母T开头的,如TKey,TValue,TOutput,TResult等
约束如下:
where T : struct
使用结构约束,类型T必须是值类型
where T : class
类约束指定,类型T必须是引用类型
where T : IFoo
指定类型T必须执行接口IFoo
where T : Foo
指定类型T必须派生于基类Foo
where T : new()
这是一个构造函数约束,指定类型T必须有一个默认构造函数,当new()与其它的约束一起使用的时候,new()放在最后
where T : U
这个约束也可以指定,类型T派生于泛型类型V。该约束也称为裸类型约束
泛型约束举例如下:
public class Person<T, T1, TC, TK, TV, TU>
where T1 : struct //约束T1必须是值类型
where T : class, new()//约束T必须是引用类型,且必须带一个无参构造函数;当new()与其它的约束一起使用的时候,new()放在最后
where TC : new() //这个类型必须带有一个无参数的构造函数【要求:1.构造函数不能为私有,2.类型不能是抽象的。】
where TK : Car //这里约束了TK类型,必须是Car类型或者是Car类型的子类
where TV : IComparable //约束类TV必须是实现IComparable接口的类型。
where TU : T //约束了TU必须是T的子类。或者是T类型。
{ public T Name { get; set; } public T1 Age { get; set; } public T Email { get; set; } public TC MyCar { get; set; } } public class Car { public Car() { this.Brand = "捷安特"; } public Car(string brand) { this.Brand = brand; } public string Brand { get; set; } } |
泛型类
如上例中Person类;类中的方法可以使用泛型类的类型参数;
泛型方法
方法中的参数可以使用泛型参数,来实现方法对于不同类型参数的支持,实现代码重用。
如:
public void Test<T>(T t) { //代码体 } |
泛型集合
ArrayList集合的升级版:List<T>
HashTable的升级版: Dictionary<K,V>
List<T>
Capacity 获取或设置该内部数据结构在不调整大小的情况下能够容纳的元素总数。
Count 获取 List<T> 中实际包含的元素数。
Add 将对象添加到 List<T> 的结尾处。
AddRange 将指定集合的元素添加到 List<T> 的末尾。
Clear 从 List<T> 中移除所有元素。
Contains 确定某元素是否在 List<T> 中。
Remove 从 List<T> 中移除特定对象的第一个匹配项。
RemoveAll 移除与指定的谓词所定义的条件相匹配的所有元素。
RemoveAt 移除 List<T> 的指定索引处的元素。
RemoveRange 从 List<T> 中移除一定范围的元素。
Reverse() 将整个 List<T> 中元素的顺序反转。
Sort() 使用默认比较器对整个 List<T> 中的元素进行排序。
ToArray 将 List<T> 的元素复制到新数组中。
Dictionary<K,V>属性方法:
Comparer 获取用于确定字典中的键是否相等的 IEqualityComparer<T>。
Count 获取包含在 Dictionary<TKey, TValue> 中的键/值对的数目。
Keys 获取包含 Dictionary<TKey, TValue> 中的键的集合。
Values 获取包含 Dictionary<TKey, TValue> 中的值的集合。
Add 将指定的键和值添加到字典中。
Clear 从 Dictionary<TKey, TValue> 中移除所有的键和值。
ContainsKey 确定 Dictionary<TKey, TValue> 是否包含指定的键。
ContainsValue 确定 Dictionary<TKey, TValue> 是否包含特定值。
//KeyValuePairs<K,V>为键值对类型
foreach(KeyValuePairs<K,V> kv in dict) { //... } |
泛型结构 Nullable<T>
[SerializableAttribute]
public struct Nullable<T>
where T : struct, new()
属性:
HasValue 当前Nullable<T>对象有值,则返回true,否者返回false
Value 获取或设置当前Nullable<T>对象的值
可空类型直接取Value值的话,当为null时,会报异常,所以可空类型在获取Value前要判断一下HasValue的值,HasValue为true时,再取值。
泛型接口
使用泛型可以定义接口,接口中的方法可以带泛型参数。
如:IComparer<T>接口
public interface IComparer<T> { // Methods int Compare(T x, T y); } |
泛型委托
public delegate int Comparsion<T>(T x, T y);
系统内置的泛型委托:
Action<T> (无返回值)
Func<T,TResult> (有返回值)
逆变(in)、协变(out)
通常,协变类型参数可用作委托的返回类型,而逆变类型参数可用作参数类型。
协变和逆变统称为“变体”。
泛型委托,泛型接口举例:
写方法对不同数组实现排序:(参照List<T>中Sort<T>方法的实现)
1.使用系统的委托类型 Comparison<T>
static void ArraySort<T>(T[] arr, Comparison<T> comparer) { //对于数组的排序方法,使用Array.Sort<T>来完成,两元素的比较方法由外部导入 Array.Sort<T>(arr, comparer); } |
2.使用自定义的泛型委托 DelegateCompare<T>
排序方法内通过调用Array.Sort<T>(T[] arr,IComparer<T> comparer);来完成,需要一个实现了IComparer<T>接口的类的对象,具体需要定义一个泛型类CompareFormattor,实现IComparer<T>泛型接口,类中对接口的实现具体是靠初始化CompareFormattor时传入的泛型委托来实现的。
//自定义泛型委托 public delegate int DelegateCompare<T>(T x, T y); //排序方法的实现 static void ArraySort<T>(T[] arr,DelegateCompare<T> dg)//参数:数组,委托 { //内部使用Array.Sort()方法,传入一个比较器的重载方法,需要实现IComparer接口的类型 IComparer<T> comparer = new ComparerFormattor<T>(dg); Array.Sort(arr,0,arr.Length, comparer); } //ComparerFormattor<T>类,实现了IComparer<T> public class ComparerFormattor<T>:IComparer<T> { DelegateCompare<T> compareDel; public ComparerFormattor(DelegateCompare<T> compareDg) { this.compareDel = compareDg; } public int Compare(T x, T y) { return compareDel(x, y); } } |
泛型的意义:
1.泛型集合:避免了装箱与拆箱:
使用ArrayList存储int类型数据,ArrayList内部维护的是object类型的数组,所以在int类型数据存储和提取的时候,会发生装箱和猜想的操作,效率低下;而使用List<int>的时候,编译器动态生成int类型的数组来存储,避免发生装箱拆箱的操作。
2.泛型方法:一个方法实现了对不同参数类型的处理,实现了代码重用。