C# 为什么协方差不能按预期工作?
为什么这不起作用?编译器应该足够聪明,知道InterfaceB需要InterfaceA,因此必须兼容C# 为什么协方差不能按预期工作?,c#,c#-9.0,C#,C# 9.0,为什么这不起作用?编译器应该足够聪明,知道InterfaceB需要InterfaceA,因此必须兼容 public interface InterfaceA { } public interface InterfaceB : InterfaceA { } public abstract class DerivedClass : BaseClass { protected override InterfaceB ItemService { get; set; } // Error, n
public interface InterfaceA
{ }
public interface InterfaceB : InterfaceA
{ }
public abstract class DerivedClass : BaseClass
{
protected override InterfaceB ItemService { get; set; } // Error, needs to be InterfaceA
}
public abstract class BaseClass
{
protected virtual InterfaceA ItemService { get; set; }
}
为什么呢
编译器应该足够聪明,知道InterfaceB需要InterfaceA,因此必须兼容
public interface InterfaceA
{ }
public interface InterfaceB : InterfaceA
{ }
public abstract class DerivedClass : BaseClass
{
protected override InterfaceB ItemService { get; set; } // Error, needs to be InterfaceA
}
public abstract class BaseClass
{
protected virtual InterfaceA ItemService { get; set; }
}
但它不兼容-您可以这样做:
DerivedClass derived = new DerivedClass();
InterfaceB ib = new InterfaceBImpl();
derived.ItemService = ib; // good so far
InterfaceA ia = new InterfaceAImpl(); // still good
BaseClass bc = derived; // still a legal downcast
bc.ItemService = ia; // seemingly good - BaseClass can store an InterfaceA
ib = derived.ServiceImpl;
这就是它爆炸的地方。您已将未实现InterfaceB的对象存储在需要InterfaceB
的属性中
实现所需功能的一种常见方法仍然是泛型:
public abstract class DerivedClass : BaseClass<InterfaceB>
{
//protected override InterfaceB ItemService { get; set; } // Error, needs to be InterfaceA
// no override needed - ItemService will now be of type InterfaceB
}
public abstract class BaseClass<T> where T : InterfaceA
{
protected T ItemService { get; set; }
}
基类表示任何InterfaceA都可以分配给ItemService,因此派生类不能将其更改为“只能将InterfaceB分配给它”。但是如果你放弃了任务,那么它就是:-
public interface InterfaceB : InterfaceA
{
}
public abstract class DerivedClass : BaseClass
{
protected override InterfaceB ItemService { get; } // no set
}
public abstract class BaseClass
{
protected virtual InterfaceA ItemService { get; }
}
它会起作用,因为没有任务……但我不确定你的实际目标你不能更改合同,而且这也没有意义。。。与
BaseClass-derived=new-DerivedClass()一样
您可以分配非接口b
的内容,如派生。ItemService=instanceOfImplementationOfInterfaceAAndNotInterfaceB代码>通过基类,您可以将任何interfaceA分配给可能未实现interfaceB的“ItemService”…答案自2009年以来没有改变-。。。正如@Selvin所指出的,问题中显示的示例没有意义——无法更改get和set的类型,也无法支持方差(co-或contra-)。你可能有理由期待它与get或set一起工作……”但从我所看到的情况来看,协变返回只适用于方法。“不,两者都适用。返回类型协方差仅适用于仅获取属性或方法,这是有意义的。协方差仅允许用于仅返回的类型。setter违反此规则。谢谢你指出这一点。是的,因为设置变量可以通过不同的方式完成,比如在派生类中重写get-only属性仍然可以由构造函数设置,我同意这一点。谢谢