从.NET2.0起,C#引入了泛型的概念。从代码编写的角度看,无疑提高了代码的编写效率;从编译器的工作来看,提高了代码的安全性,泛型的引入避免了几乎所有的运行时的异常,在以前的版本中,系统需要对类型进行检查,对这些异常进行处理,包括栈审核和栈解退,对性能造成影响;同时,在以前版本的Framework中,强制使用System.Object类型,只有在使用之前才将其动态强制转换为需要的类型,这个过程涉及到拆箱和装箱的操作,可能对性能,尤其是使用值类型的性能造成巨大的影响。
编译器对参数为引用类型和值类型的泛型的处理是不同的:(有个概念:所有参数都已经明确给出的泛型类型叫做封闭泛型类型;而仅仅给出部分的叫做开放泛型类型)
1.引用类型。被JIT编译后只生成一份代码,因为所有的引用泛型在申请空间的时候,都是申请一个引用所占的空间。
2.值类型。首先,JIT将创建一个新的IL类,用来表示该封闭类型。(即,根据使用的参数类型创建一个具体值类型的封闭类型);然后,编译成指令。这里并不是在某个类加载时生成完整的指令,而是保存为两部分:一是为每种用值类型作为参数的封闭泛型类型保存一份IT定义的副本(即上面的);二是为每种值类型作为参数的封闭类型保存一份保存一份所调用的方法的机器码的副本。这样的在创建单个某个值类型的对象时,会增加内存,但是避免了装箱和拆箱的操作,降低了值类型的代码和数据所占的空间;同时,对于多个同值类型的对象时,将降低额外生成的IL代码量(因为只需要一份)。
每个System.Collections命名空间中的原有类或接口的新的或者改进版本的位于System.Collections.Generics中,同时也新增了几个:(注意:“扩展”代表是从原来的类中继承而来,“替换”代表由于原有接口没有包含新接口的签名,新接口的签名方法无法与原来接口保持一致,而没有继承)
原有类型 |
新类型 |
更改方式 |
ArrayList |
List<T> |
替代 |
Stack |
Stack<T> |
替代 |
Hashtable |
Dictionary<K,V> |
替代 |
Query |
Query<T> |
替代 |
无 |
LinkedList<T> |
新增 |
无 |
SortedList<T> |
新增 |
IList |
IList<T> |
扩展 |
IDictionary |
IDictionary<T> |
替代 |
IEmumerable |
IEmumerable<T> |
扩展 |
IComparer |
IComparer<T> |
替代 |
ICollection |
ICollection<T> |
替代 |
无 |
IEquateable<T> |
新增 |
无 |
IEqualityComparer<T> |
新增 |
下面说说几点建议:
1.再重写Equals方法时,实现IEquatable<T>接口。
public interface IEquatable<T>
{
bool Equals(T other);
}
2.若需对定义在其他类库中的类型进行比较,请实现IEqualityComparer<T>。
/**使用Default属性,将检查参数T是否实现了IEquatable<T>接口。若实现,则返回使用了该类型的接口,否则使用System.Object的。*/
public class MyComparer:EqualityComparer<MyClass>
{
public override bool Equals(MyClass x, MyClass y)
{
return EqualityComarer<MyClass>.Default.Equals(x,y);
}
public override int GetHashCode(MyClass c)
{
return EqualityComparer<MyClass>.Default.GetHashCode(c);
}
}
3.使用泛型委托
使用泛型委托可以在不同的情况下,传入不同函数指针。
public delegate TOutput Converter<TInput, TOutput>(TInput input);
//创建一个Convert委托
public static IEnumerable<TOutput> Transform<TInput, TOutput>(IEnumerable<TInput> theCol, Converter<TInput,TOutput> transformer)
{
foreach(TInput source in theCol)
yield return transformer(source);
}
泛型委托还简化了事件相关的代码。
public delegate void EventHandler<T>(object sender, T args) where T:EventArgs;
public event EventHandler<T> OnRaiseMyEvent;
4.坚持最小化约束的原则。例如在默认构造函数约束时,可以将new()约束用default()的调用来代替,该操作符用来将变量初始化为默认值(注意不是去调用默认的构造函数)
public delegate bool Predicate<T>(T value);
public static T MyMethodWithDefault<T>(this IEnumeraable<T> sequence, Predicate<T> test)
{
foreach(T value in squence)
{
if(test(value)) return value;
return default(T);
}
}
/**
*默认的构造函数约束是没有必要的,因为并不需要每个使用该方法的类都必
*需要有默认的构造函数,这样会大大减少该函数的使用范围,也未JIT增加
*了不必要的检查工作
*/
public static T MyMethodWithOutDefault<T>(this IEnumeraable<T> sequence, Predicate<T> test) where T:new()
{
foreach(T value in squence)
{
if(test(value)) return value;
return new T();
}
}
分享到:
相关推荐
C#泛型 C#泛型是一种强类型机制,允许在编译时指定类型参数,从而提高代码的灵活性和可重用性。泛型可以应用于类、结构、接口和委托等多种类型。 1. 泛型类声明 泛型类声明是一个需要提供类型参数以形成实际类型...
主要介绍编写高质量的代码有助于改善C#程序,在开发过程中集合用的比较多,如何把集合使用好,在开发过程必须掌握的技巧,下面这篇文章就给大家详细介绍编写高质量代码改善C#程序——使用泛型集合代替非泛型集合...
这是我整理的C#中关于泛型的详细讲解,虽然分数高点,算是辛苦费了。
C# 工具类 泛型转JSON 使用 Newtonsoft.Json 转换JSON
C#的泛型C#的泛型
谈谈关于Microsoft Visual Studio 2008中C#和java泛型的区别
很多初学C#编程的人可能对泛型列表List的使用不是很清楚,希望这个例子能帮助大家.
学S2的同学应该会遇到使用泛型集合List存储数据,并在DataGridView里显示数据。
关于如何在C#中使用泛型,希望对大家有帮助
在2005年底微软公司正式发布了C# 2.0,与C# 1.x相比,新版本增加了很多新特性,其中最重要的是对泛型的支持。通过泛型,我们可以定义类型安全的数据结构,而无需使用实际的数据类型。这能显著提高性能并得到更高质量...
C#2.0 泛型和强制类型转换C#2.0 泛型和强制类型转换C#2.0 泛型和强制类型转换
c#实现对泛型数组排序
本书延续了Effective系列图书的风格,针对 C# 2.0和 C# 3.0中添加的新特性给出了实用的建议。书中的 50个条目自成一体且又丝丝相扣,这些条目按照泛型、多线程开发、C#设计模式、C# 3.0语言增强、LINQ以及杂项等主题...
C#中关于泛型的一些讲解.............................................................
C# 委托、泛型与事件 C# 委托、泛型与事件 C# 委托、泛型与事件 C# 委托、泛型与事件
讓初學者很快的學會C# 2.0中泛型编程初级入门教程
C#【泛型】实现的【通用】结构体转字节数组,包含网上收集的网页参考资料、非通用的【StructTest】工程、泛型实现的通用【Struct2BytesGenericType】工程。 VS2010编译运行。
泛型类、泛型方法、泛型接口、泛型委托 泛型类、泛型方法、泛型接口、泛型委托
很好用的C#读写缓存泛型公共类,C#获取 创建 修改缓存泛型公共方法