可能重复:
Does C# support return type covariance?
Why can’t I implement an Interface this way?
请考虑以下事项:
public interface IAnimal {
}
public class Animal : IAnimal {
}
public interface ICage {
IAnimal SomeAnimal {get;}
}
public class Cage : ICage{
public Animal SomeAnimal { get; set; }
}
我已经阅读了很多关于IEnumerable的协方差和逆变的东西,但我不知道如何让上面的代码工作。我收到错误“Cage没有实现接口成员IAnimal”。既然它定义了动物,它比IAnimal更明确,似乎协方差应该照顾我。
我错过了什么?提前谢谢。
答案 0 :(得分:6)
目前在C#中无法实现。
理论上语言设计者可以添加它,但它们还没有。他们可能会也可能不会决定将其添加到潜在的未来版本的C#。
最好的解决方法可能是:
public class Cage : ICage
{
public Animal SomeAnimal { get; set; }
IAnimal ICage.SomeAnimal
{
get { return SomeAnimal }
}
}
答案 1 :(得分:2)
引自Eric Lippert,回答我在这里问同样的问题: Why can't I implement an Interface this way?
C#不支持返回类型协方差 接口实现或虚拟方法覆盖。看到这个 问题详情:
Does C# support return type covariance?
C#确实支持接口的通用协方差和逆变 以及用于构造的引用类型和委托类型 从C#4开始输入参数。
转换方法时,C#确实支持返回类型协方差 将引用类型返回给返回类型为的委托类型 兼容的参考类型。 (同样它支持参数类型 逆变。)
如果这个主题让你感兴趣,我写了很多文章 讨论C#所做和不做的各种版本的差异 支持。参见
http://blogs.msdn.com/b/ericlippert/archive/tags/covariance+and+contravariance/
了解详情。
答案 2 :(得分:2)
public interface IAnimal {
}
public class Animal : IAnimal {
}
public interface ICage {
IAnimal SomeAnimal {get;}
}
public class Cage : ICage{
public Animal SomeAnimal { get; set; }
}
public class AnotherAnimal : IAnimal {
}
Cage c = new Cage();
ICage ic = (ICage)c;
ic.Animal = new AnotherAnimal();
这将无效,因为AnotherAnimal
实施IAnimal
,但它不是Animal
。
修改
只有在界面中定义了setter时,上述内容才有意义。因为没有,这里正确的答案是在C#中无法实现所需的功能;它是一种未包含在该语言中的功能。
答案 3 :(得分:2)
要获得协方差,你应该有这样的东西:
public interface IAnimal {
}
public class Lion : IAnimal {}
public class Sheep : IAnimal {}
// note the "out" on the T type parameter
public interface ICage<out T> where T:IAnimal {
T SomeAnimal {get;}
}
public class Cage<T> : ICage<T> where T:IAnimal {
public T SomeAnimal { get; set; }
}
你现在可以这样做:
// without covariance on ICage you can't assign a 'Cage<Sheep>' to 'ICage<IAnimal>'
ICage<IAnimal> sheeps = new Cage<Sheep>() {SomeAnimal=new Sheep()};
ICage<IAnimal> lions = new Cage<Lion>() {SomeAnimal=new Lion()};
或者这个(用绵羊和狮子的笼子创建Cage<IAnimals>
的异构列表),这是一个等价但可能更有用的例子:
// without covariance on ICage it errors: cannot convert from 'Cage<Sheep>' to 'ICage<IAnimal>'
var zoo = new List<ICage<IAnimal>>{
new Cage<Sheep> {SomeAnimal=new Sheep()},
new Cage<Lion> {SomeAnimal=new Lion()},
};
如果您尝试从out
声明中删除ICage
,则会看到差异。