日期:2014-05-18 浏览次数:20928 次
在C#引入泛型之前,如果一个类或者一个方法想要支持多种类型,它就不得不把相应的参数或者返回值定义为object类型,这就意味着代码在执行的过程中需要很多的转型,并不是说你的代码一定不要用到转型,但是转型确实会带来很多潜在的问题,因为它将本该属于编译时的类型检查延迟到了运行时,而且也会带来一定的性能问题(装箱和拆箱)。
C#2引入了泛型,包括两种形式的泛型:泛型类型和泛型方法。下面说一下和泛型有关的一些特性:
一、泛型约束
C#泛型支持四种类型的约束,但是它们使用同样的语法:
引用类型约束
对于引用类型的约束,泛型对象之间可以通过==和!=进行比较,但是需要注意的是,除非指定了其它约束,否则只会比较引用本身(即使引用对象类型重载了比较方法),使用转换类型约束,重载的比较方法才会被编译器调用。
class RefSample<T> where T : class
值类型约束
对于值类型的约束,泛型对象之间不允许使用==和!=进行比较。
class ValSample<T> where T : struct
构造函数类型约束
构造函数类型约束类型要包含无参构造函数。这样就可以构造泛型对象实例。
public T CreateInstance<T>() where T : new() { return new T(); }
转型类型约束允许你指明一种类型,使得参数类型必须能被隐式转换成指明的类型。
转换类型约束非常重要,因为你可以用泛型对象调用指明类型的方法。例如,对于T : IComparable<T>,这意味着你能直接比较两个T类型的对象。
class Sample<T> where T : Stream, IEnumerable<string>, IComparable<int>
1)没有一个类型可以既是引用类型又是值类型,所以同时做引用类型约束和值类型约束是不允许的。
2)每一个值类型都有一个无参构造函数,所以不能同时有值类型约束和构造函数类型约束。
3)对于多个转换类型约束,最多只能有一个类类型,而且类类型必须放在接口类型的前边。而且每一个类型转换约束只能出现一次。
4)不同的参数类型可以有不同的约束,它们通过各自的where来指定。
下面列出了一些合法与不合法的约束混合使用:
Valid class Sample<T> where T : class, IDisposable, new() class Sample<T> where T : struct, IDisposable class Sample<T,U> where T : class where U : struct, T class Sample<T,U> where T : Stream where U : IDisposable Invalid class Sample<T> where T : class, struct class Sample<T> where T : Stream, class class Sample<T> where T : new(), Stream class Sample<T> where T : IDisposable, Stream class Sample<T> where T : XmlReader, IComparable, IComparable class Sample<T,U> where T : struct where U : class, T class Sample<T,U> where T : Stream, U : IDisposable
C#编译器允许在调用泛型方法的时候不用显式指明参数类型,而是通过方法中传递的参数(注意不是返回值类型)进行类型推断,注意的是这只针对泛型方法有用(对泛型类型无效),例如:
static List<T> MakeList<T>(T first, T second) ... List<string> list = MakeList<string>("Line 1", "Line 2");
对于这个泛型方法,编译器可以根据参数的类型推断出T,因此允许用户无需显式指明类型:
List<string> list = MakeList("Line 1", "Line 2");
很多时候我们需要在泛型中使用默认值,C#使用default(T) 表达式返回当前泛型类型的默认值。
四、泛型中的比较
如果参数类型没有被约束,你只能使用==/!=运算符将值和null进行比较,不能用这两个操作符比较两个T类型的值。
如果参数类型被约束为值类型,那么==/!=根本就不能被应用。
如果参数类型被约束为引用类型,那么==/!=只会比较两者的引用。
如果参数类型被约束为为继承自重载了==/!=的类或接口,那么将使用重载的==/!=进行比较
例如:
static bool AreReferencesEqual<T>(T first, T second) where T : class { return first == second; } string str = "World"; string str1 = "Hello" + str; string str2 = "Hello" + str; Console.WriteLine(str1 == str2); Console.WriteLine(AreReferencesEqual(str1, str2)); Output: True False