Jam*_*man 60 c# casting covariance
协方差和向上转换之间有什么区别,或者更具体地说,它们为什么被赋予不同的名称?
我已经看到以下示例称为"向上转换":
string s = "hello";
object o = s; //upcast to 'string' to 'object'
Run Code Online (Sandbox Code Playgroud)
然而,我见过以下所谓的'协方差':
string[] s = new string[100];
object[] o = s;
IEnumerable<string> ies = new List<string>();
IEnumerable<object> ieo = ies;
Run Code Online (Sandbox Code Playgroud)
现在,对于我未经训练的眼睛,协方差似乎与向上转换相同,除了它指的是集合的铸造.(关于逆变和向下转换,可以做出类似的陈述).
它真的那么简单吗?
jas*_*son 57
现在,对于我未经训练的眼睛,协方差似乎与向上转换相同,除了它指的是集合的铸造.(关于逆变和向下转换,可以做出类似的陈述).
它真的那么简单吗?
协方差不是关于向上转换,虽然我可以看出为什么你认为它是相关的.
协方差是关于以下非常简单的想法.假设你有一个derivedSequence类型的变量IEnumerable<Derived>.假设你有一个baseSequence类型的变量IEnumerable<Base>.在这里,Derived源于Base.然后,使用协方差,以下是合法分配,并发生隐式引用转换:
baseSequence = derivedSequence;
Run Code Online (Sandbox Code Playgroud)
请注意,这不是向上转发.这并不是说该案件IEnumerable<Derived>从派生IEnumerable<Base>.相反,它是协方差,允许您将变量的值赋给derivedSequence变量baseSequence.我们的想法是类型的变量Base可以从类型的对象中分配Derived,并且由于IEnumerable<T>其参数是协变的,因此IEnumerable<Derived>可以将类型的对象分配给类型的变量IEnumerable<Base>.
当然,我还没有真正解释协方差是什么.一般来说,协方差是关于以下简单的想法.假设你有一个F从类型到类型的映射(我将表示这种映射F<T>;给定一个类型,T它在映射下的图像F是F<T>.)假设这个映射具有以下非常特殊的属性:
如果
X赋值兼容Y,那么F<X>赋值也兼容F<Y>.
在这种情况下,我们说它F的参数是协变的T.(这里,说" A赋值兼容B"where A和B是引用类型意味着实例B可以存储在类型的变量中A.)
在我们的情况下,IEnumerable<T>在C#4.0,从实例隐式引用转换IEnumerable<Derived>到IEnumerable<Base>如果Derived源自Base.保留了赋值兼容性的方向,这就是为什么我们说它IEnumerable<T>的类型参数是协变的.
ant*_*oft 15
IEnumerable<string>不是源于IEnumerable<object>,所以他们之间的演员不是向上倾斜.IEnumerable在其类型参数中是协变的,字符串是 从对象派生的,因此允许强制转换.
它们是不同概念的原因在于,与向上转换不同,并不总是允许协方差.类型系统的设计者很容易IList<Cat>被认为是"派生"的IList<Animal>,但后来我们遇到了问题:
IList<Cat> cats = new List<Cat>();
IList<Animal> animals = cats;
animals.Add(new Dog()); //Uh oh!
Run Code Online (Sandbox Code Playgroud)
如果这是允许的,现在我们的cats列表将包含一个Dog!
相反,IEnumerable<T>接口无法添加元素,因此这完全有效(在C#4.0中):
IList<Cat> cats = new List<Cat>();
IEnumerable<Animal> animals = cats;
//There's no way to add things to an IEnumerable<Animal>, so here we are ok
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2606 次 |
| 最近记录: |