一,C#泛型概述
• 基于object解决方案存在的问题
– 性能问题:
• 值类型Push时要装箱处理,Pop时要取消装箱处理,造成更多的垃圾碎片,增加垃圾收集的负担
• 引用类型也有强制转换的开销
– 类型安全问题(更为严重)
• 编译时任务类型都可以转换成object,无法保证运行时的类型安全
二,什么是泛型?
• 通过泛型可以定义类型安全类,而不会损害类型安全、性能或工作效率
三,泛型是如何实现的?
• 在.NET 2.0 中,泛型在IL(中间语言)和CLR 本身中具有本机支持
• 编译泛型类时,就像编译其他类一样,泛型仅保留一个占位符
• 而用特定类型实例化泛型代码,编译时会将泛型替换为实例化的特定类型
使用ILDAM工具可以查看到编译结构,stack<T> ---> stack`1<int> (其中`1 指定有1个泛型参数)
四,泛型的好处
• 一次性地开发、测试和部署代码,通过任何类型(包括将来的类型)来重用它
• 编译器支持和类型安全
• 不会强行对值类型进行装箱和取消装箱,或者对引用类型进行向下强制类型转换,所以性能得到 显著提高
– 值类型,性能通常会提高200%
– 引用类型,在访问该类型时,可以预期性能最多提高100%(当然,整个应用程序的性能可能会提高,也可能不会提高)
五,在结构中使用泛型
• 轻量级的结构中使用泛型
• 基于object解决方案存在的问题
– 性能问题:
• 值类型Push时要装箱处理,Pop时要取消装箱处理,造成更多的垃圾碎片,增加垃圾收集的负担
• 引用类型也有强制转换的开销
– 类型安全问题(更为严重)
• 编译时任务类型都可以转换成object,无法保证运行时的类型安全
1
Stack stack = new Stack();
2
stack.Push(“test”);
3
//This compiles, but is not type safe,
4
//and will throw an exception:
5
int number = (int)stack.Pop();
Stack stack = new Stack(); 2
stack.Push(“test”); 3
//This compiles, but is not type safe, 4
//and will throw an exception: 5
int number = (int)stack.Pop(); 二,什么是泛型?
• 通过泛型可以定义类型安全类,而不会损害类型安全、性能或工作效率
1 public class Stack <T>
2 {
3 T[] m_Items;
4
5 public void Push(T item)
6 {
}
7
8 public T Pop()
9 {
}
10 }
2 {
3 T[] m_Items;
4
5 public void Push(T item)
6 {
}7
8 public T Pop()
9 {
}10 }
三,泛型是如何实现的?
• 在.NET 2.0 中,泛型在IL(中间语言)和CLR 本身中具有本机支持
• 编译泛型类时,就像编译其他类一样,泛型仅保留一个占位符
• 而用特定类型实例化泛型代码,编译时会将泛型替换为实例化的特定类型
使用ILDAM工具可以查看到编译结构,stack<T> ---> stack`1<int> (其中`1 指定有1个泛型参数)
四,泛型的好处
• 一次性地开发、测试和部署代码,通过任何类型(包括将来的类型)来重用它
• 编译器支持和类型安全
• 不会强行对值类型进行装箱和取消装箱,或者对引用类型进行向下强制类型转换,所以性能得到 显著提高
– 值类型,性能通常会提高200%
– 引用类型,在访问该类型时,可以预期性能最多提高100%(当然,整个应用程序的性能可能会提高,也可能不会提高)
五,在结构中使用泛型
• 轻量级的结构中使用泛型
public struct Point<T>
{
public T X;
public T Y;
}
Point<int> point;
point.X = 1;
point.Y = 2;
Point<double> point;
point.X = 1.2;
point.Y = 3.4;
{
public T X;
public T Y;
}
Point<int> point;
point.X = 1;
point.Y = 2;
Point<double> point;
point.X = 1.2;
point.Y = 3.4;
七,Default关键字
• 假设您不希望在堆栈为空时引发异常,而是希望返回堆栈中存储的类型的默认值
– 值类型返回0(整型、枚举和结构)
– 引用类型返回null
• 如果是基于object,则可以简单的返回null

八,泛型别名
• 在文件头部使用using为特定类型取别名
• 别名作用范围是整个文件
using List = LinkedList<int,string>;
class ListClient
{
static void Main(string[] args)
{
List list = new List();
list.AddHead(123,"AAA");
}
}
class ListClient
{
static void Main(string[] args)
{
List list = new List();
list.AddHead(123,"AAA");
}
}
九,泛型约束概述
如果需要在泛型类中实例化参数,则需要为泛型参数指定 new() 约束,否则编译器不知道是否有匹配的构造函数。


10,泛型约束-引用/值类型约束
• 可以使用struct 约束将一般类型参数约束为值类型(例如,int、bool 和enum),或任何自定义结构
public class MyClass<T> where T : struct
{...}
• 同样,可以使用class 约束将一般类型参数约束为引用类型(类)
public class MyClass<T> where T : class
{...}

浙公网安备 33010602011771号