发现很少有集中讨论C#可变性限制的中文博文(要么就是一大段文字中夹杂很多凌乱的部分),所以写发篇博文,集中讨论,这些限制基本是基于安全考虑,亦或者根本难以实现而产生的。
注:本文不再解释什么是可变性,以及本文所讨论的问题都基于.NET 4至.NET 4.5。所有地方我都力求简洁。
好了,废话不说了,开始吧。
1.可变性只支持引用转换,禁止值类型转换、装箱转换(好吧其实就是值类型转换)、和用户自定义类型转换。
任何可变性转换都是一种引用转换,这种转换是类型安全的,他只能操作引用类型,不会对引用的二进制表示产生影响也不会创建新的对象。
2.只有接口和委托可以有可变的类型参数。
3.out修饰的参数是不变的。
这样说不太直观。
比如一个委托 delegate int GetXXX<T>(string name,out T value)
此时T是不可以协变的。
因为CLR中并没有out参数,(ref 和out也不可以使函数重载),out参数是含有[Out]特性的ref参数,而ref参数意味着(对于CLR来说)数据是既可以输入也可以输出的,所以T不可变。
4.必须显示指定可变性(in/out)而不是由编译器推断。
强迫开发者显示指定可以增强安全性,比如一个新的变化可用的时候,也许会影响重载。
5.不要在多播委托中使用可变性。
这应该算一个bug吧……不应该允许这样的代码,而且还不能在编译时发现问题。一个策略是为将产生协变或者逆变的委托创建一个目标类型的委托来包裹他——当然,如果你都意识到了这个问题,你不大可能再写出这样的代码。
暂时就写到这啦。