ena*_*ash 0 c# covariance contravariance c#-4.0
abstract class A<T> {
List<T> Items { get; set; }
}
class B {}
class C : A<B> {}
class D : B {}
class E : A<D> {}
static class X {
public A<B> GetThing(bool f) {
return f ? new E() : new C();
}
}
Run Code Online (Sandbox Code Playgroud)
无法确定条件表达式的类型,因为"ConsoleApplication4.E"和"ConsoleApplication4.C"之间没有隐式转换
现在我得到了"为什么"(我认为),但我看不出如何编译.我想我必须创建一个定义某种方差的接口并从中继承,但我不确定.但无论如何,E()都应该继承C().
任何接受者?
TIA
Eri*_*ert 15
要在C#中使用泛型差异,您必须满足以下所有条件:
您的程序符合条件1和条件5,但不符合条件2,3或4.
没有办法得到你想要的变化,因为你想要一些违反条件4的东西.观察当我们满足除条件4之外的所有条件时会发生什么:
// Suppose this declaration were legal:
interface IMyCollection<out T>
{
List<T> Items { get; set; }
}
class Animal {}
class AnimalCollection : IMyCollection<Animal>
{
public List<Animal> { get; set; }
}
class Giraffe : Animal {}
class GiraffeCollection : IMyCollection<Giraffe>
{
public List<Giraffe> { get; set; }
}
static class X
{
public IMyCollection<Animal> GetThing()
{
// IMyCollection is covariant in T, so this is legal.
return new GiraffeCollection();
}
}
class Tiger : Animal {}
...
IMyCollection<Animal> animals = X.GetThing();
// GetThing() actually returns a GiraffeCollection
animals.Items = new List<Animal>() { new Tiger(); }
Run Code Online (Sandbox Code Playgroud)
长颈鹿系列现在包含一个包含老虎的动物列表.
如果你要使用方差,你必须是类型安全的.因为编译器无法将方差注释确定为类型安全,所以它拒绝IMyCollection的声明.
让我们看看我们如何做到这一点并保持类型安全.问题是Items可以通过界面写入.
interface IMyCollection<out T>
{
IEnumerable<T> Items { get; }
}
class Animal {}
class AnimalCollection : IMyCollection<Animal>
{
public IEnumerable<Animal> { get { yield return new Tiger(); } }
}
class Giraffe : Animal {}
class GiraffeCollection : IMyCollection<Giraffe>
{
public IEnumerable<Giraffe> { get { yield return new Giraffe(); } }
}
static class X
{
public IMyCollection<Animal> GetThing()
{
return new GiraffeCollection();
}
}
class Tiger : Animal {}
...
MyCollection<Animal> animals = X.GetThing();
// GetThing() actually returns a GiraffeCollection
foreach(Animal animal in animals.Items) { ... }
// Items yields a giraffe, which is an animal
Run Code Online (Sandbox Code Playgroud)
完全类型安全.这将是一个合法的C#4计划.
如果C#4中协方差和逆变的设计细节让您感兴趣,您可以考虑阅读我关于该主题的十几篇文章.你可以在这里找到它们:
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/
请注意,这些是按最近到最近的顺序列出的; 从底部开始.
如果您特别感兴趣的是确定接口注释何时有效的规则,请参阅本文(我刚刚发现并解决了一些错误,所以我很高兴我们进行了这次对话.)
http://blogs.msdn.com/b/ericlippert/archive/2009/12/03/exact-rules-for-variance-validity.aspx