协方差和上传之间的区别

协变和上传之间有什么区别,或者更具体地说,为什么他们有不同的名字?

我已经看到下面的例子被称为“上传”:

string s = "hello"; object o = s; //upcast to 'string' to 'object' 

鉴于以下我所见到的“协变”:

 string[] s = new string[100]; object[] o = s; IEnumerable<string> ies = new List<string>(); IEnumerable<object> ieo = ies; 

现在,对我未经训练的人来说,协变似乎与上演一样,只不过它指的是collections的铸造。 (关于逆转和下转也可以做出类似的说法)。

这真的很简单吗?

现在,对我未经训练的人来说,协变似乎与上演一样,只不过它指的是collections的铸造。 (关于逆转和下转也可以做出类似的说法)。

这真的很简单吗?

协变不是关于临近的,尽pipe我可以看出为什么你认为它是相关的。

协变是关于以下非常简单的想法。 假设您有一个IEnumerable<Derived>types的variablesderivedSequence 。 假设您有一个IEnumerable<Base>types的variablesbaseSequence 。 在这里, Derived派生自Base 。 然后,使用协方差,下面是一个合法的赋值,并发生一个隐式的参考转换:

 baseSequence = derivedSequence; 

请注意,这不是upcasting。 IEnumerable<Derived>不是由IEnumerable<Base>派生的。 相反,协变性允许您将variablesderivedSequence的值分配给variablesbaseSequence 。 这个想法是Basetypes的variables可以从Derivedtypes的对象中分配,并且由于IEnumerable<T>在其参数中是协变的,所以IEnumerable<Derived>types的对象可以被分配给IEnumerable<Base>types的variables。

当然,我还没有真正解释过什么样的协变性。 一般来说,协变是关于以下简单的想法。 假设你有一个从types到types的映射F (我将用F<T>表示这个映射;给定一个typesT ,映射F下的映像是F<T> 。假设这个映射有下面的特殊属性:

如果XY分配兼容,则F<X>也与F<Y>兼容。

在这种情况下,我们说F是参数T协variables。 (这里,要说“ A是与B兼容的分配”,其中AB是引用types,意味着B实例可以存储在typesAvariables中。)

在我们的例子中,C#4.0中的IEnumerable<T> ,如果Derived是从Base派生的,则从IEnumerable<Derived>实例到IEnumerable<Base>的隐式引用转换。 赋值兼容性的方向被保留下来,这就是为什么我们说IEnumerable<T>在它的types参数中是协变的。

投射指的是改变对象和expression式的静态types。

差异是指在某些情况下(如参数,generics和返回types) 的types可交换性或等价性

IEnumerable<string>不是从IEnumerable<object>派生的,因此它们之间的转换不是向上转换的。 IEnumerable在其types参数中是协变的,string从对象派生的,因此允许强制转换。

他们是不同的概念的原因是,不像upcasting,协变并不总是允许的。 对于types系统的devise者来说,将IList<Cat>视为IList<Animal> “派生”是容易的,但是我们遇到了一些问题:

 IList<Cat> cats = new List<Cat>(); IList<Animal> animals = cats; animals.Add(new Dog()); //Uh oh! 

如果这是允许的,现在我们的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 

从我可以收集的协方差中删除了之前的upcast之后显式向下转换的需要。 通常情况下,如果向上转换对象,则只能访问基types方法和属性,而在协variables方面,似乎可以通过在派生类声明中使用更多派生typesreplace较小的派生types来暗示下调。