.net基础—泛型
泛型
泛型在 .NET Framework 2.0 中首次引入,它本质上是一个“代码模板”,可让开发者定义类型安全数据结构,无需处理实际数据类型。 例如,List
为方便理解泛型的作用,让我们看看添加泛型之前和之后的一个特定类:ArrayList。 在 .NET Framework 1.0 中,ArrayList 元素属于 Object 类型。 添加到集合的任何元素都会以静默方式转换为 Object。 从列表读取元素时,会发生相同的情况。 此过程称为装箱和取消装箱,它会影响性能。 但除了性能之外,在编译时无法确定列表中的数据的类型,这会形成一些脆弱的代码。 泛型解决了此问题,它可以定义每个列表实例将要包含的数据类型。 例如,只能将整数添加到 List
泛型还可以在运行时使用。 运行时知道你要使用的数据结构类型,并可以更高效地将数据结构存储在内存中。
泛型的性能
通过执行一亿次三种不同类型方法:确定参数类型的方法、Object参数类型的方法、 泛型参数类型的方法,来看一下它们的耗时情况。
1 class Program 2 { 3 static void Main(string[] args) 4 { 5 int testVal = 123; 6 long commonSecond = 0; 7 long objectSecond = 0; 8 long genericSecond = 0; 9 10 { 11 // 调用确定参数类型的方法的耗时 12 Stopwatch watch = new Stopwatch(); 13 watch.Start(); 14 for (int i = 0; i < 100000000; i++) 15 { 16 ShowInt(testVal); 17 } 18 watch.Stop(); 19 commonSecond = watch.ElapsedMilliseconds; 20 } 21 { 22 // 调用Object参数类型的方法的耗时 23 Stopwatch watch = new Stopwatch(); 24 watch.Start(); 25 for (int i = 0; i < 100000000; i++) 26 { 27 ShowObject(testVal); 28 } 29 watch.Stop(); 30 objectSecond = watch.ElapsedMilliseconds; 31 } 32 { 33 //调用泛型参数类型的方法的耗时 34 Stopwatch watch = new Stopwatch(); 35 watch.Start(); 36 for (int i = 0; i < 100000000; i++) 37 { 38 Show<int>(testVal); 39 } 40 watch.Stop(); 41 genericSecond = watch.ElapsedMilliseconds; 42 } 43 Console.WriteLine("commonSecond = {0} \n objectSecond = {1} \n genericSecond = {2} ", 44 commonSecond, objectSecond, genericSecond); 45 46 } 47 48 ///49 /// 确定参数类型的方法 50 /// 51 /// 52 private static void ShowInt(int valParam) 53 { 54 55 } 56 /// 57 /// Object参数类型的方法(类型不确定通过用obj 来实现通用) 58 /// 59 private static void ShowObject(int objParam) 60 { 61 62 } 63 /// 64 /// 泛型参数类型的方法 65 /// 66 private static void Show (int tParam) 67 { 68 69 } 70 71 }
上面代码的执行效果:

通过上图可以得出:确定参数类型的方法和 泛型参数类型的方法相差不是很大,Object参数类型的方法的方法性能最差,Object慢的原因是多了一个装箱操作。
协变逆变
在C# 4.0之前,所有的泛型类型都是不变量——即不支持将一个泛型类型替换为另一个泛型类型,即使它们之间拥有继承关系,简而言之,在C# 4.0之前的泛型都是不支持协变和逆变的。
C# 4.0通过两个关键字:out和in来分别支持以协变和逆变的方式使用泛型。
class Program
{
static void Main(string[] args)
{
List birdList1 = new List();
// vs提示错误
//List birdList2 = new List();
List birdList3 = new List().Select(c => (Bird)c).ToList();
//协变 IEnumerable既可以接受父类也可以接受子类
IEnumerable birdList4 = new List();
IEnumerable birdList5 = new List();
//逆变 ICustomerListIn既可以接受父类也可以接受子类
ICustomerListIn customerList1 = new CustomerListIn();
ICustomerListIn customerList2 = new CustomerListIn();
}
}
class Bird
{
}
class Sparrow : Bird
{
}
///
/// out 协变 只能是返回结果
///
///
public interface ICustomerListOut
{
T Get();
}
public class CustomerListOut : ICustomerListOut
{
public T Get()
{
return default(T);
}
}
///
/// in 逆变 只能是参数
///
///
public interface ICustomerListIn
{
void Show(T t);
}
public class CustomerListIn : ICustomerListIn
{
public void Show(T t)
{ }
}