c#对象接口返回类型协方差
C#编译器: 错误CS0738:c#对象接口返回类型协方差,c#,generics,types,covariance,covariant-return-types,C#,Generics,Types,Covariance,Covariant Return Types,C#编译器: 错误CS0738:Field'未实现接口成员Field.Value.get'和最佳实现候选者Field.Value.get'返回类型T'与接口成员返回类型'object'不匹配 public interface Field { object Value {get;} } public class MyField<T> : Field { T _value; public T Value { get {
Field'未实现接口成员
Field.Value.get'和最佳实现候选者Field.Value.get'返回类型
T'与接口成员返回类型'object'不匹配
public interface Field
{
object Value {get;}
}
public class MyField<T> : Field
{
T _value;
public T Value
{
get
{
return _value;
}
}
}
公共接口字段
{
对象值{get;}
}
公共类MyField:Field
{
T_值;
公共价值
{
收到
{
返回_值;
}
}
}
为什么??List废话,“返回类型协方差”,废话,“你不能” 他们没有就如何编译这个beast提出解决方案或解决方法。 要求:
1) 字段是不能接受泛型的接口。被称为“统一”的邪恶框架禁止泛型。
2) “implements Field”(实现字段)的字段
您在界面中不使用模板类型,而是使用对象。请尝试以下操作:
interface Field<T>
{
T Value { get; }
}
public class MyField<T> : Field<T>
{
private T _value;
public T Value
{
get
{
return _value;
}
}
}
接口字段
{
T值{get;}
}
公共类MyField:Field
{
私人T_值;
公共价值
{
收到
{
返回_值;
}
}
}
也许你需要这个。因为每个数据类型都继承对象,而不是相反。我想这就是协方差问题即将来临的原因 我不确定这正是你想要的。但是如果你的界面不能通用,那么这就是可行的
public interface Field
{
object Value {get;}
}
public class MyField<T> : Field
{
public T _value;
public T MyTypedValue
{
get
{
return _value;
}
}
public object Value
{
get
{
return _value;
}
}
}
公共接口字段
{
对象值{get;}
}
公共类MyField:Field
{
公共T_值;
公共T MyTypedValue
{
收到
{
返回_值;
}
}
公共对象价值
{
收到
{
返回_值;
}
}
}
您可以显式地实现接口
相同的模式用于非泛型版本的IEnumerable
和泛型IEnumerable
您也可以这样做,并具有通用接口
public interface Field
{
object Value { get; }
}
public interface Field<T> : Field
{
new T Value { get; }
}
public class MyField<T> : Field<T>
{
public T Value { get; } // generic
object Field.Value => Value; // non generic
}
公共接口字段
{
对象值{get;}
}
公共接口字段:字段
{
新的T值{get;}
}
公共类MyField:Field
{
公共T值{get;}//generic
对象字段。Value=>Value;//非泛型
}
现在,如果您手上有字段
,您可以愉快地使用T
。如果有字段
,则会得到值的对象形式T
公共类字段:字段
public class Field<T> : Field
{
T _value;
//specific interface implementation
object Field.Value
{
get
{
return _value;
}
}
public T Value
{
get
{
return _value;
}
}
}
{
T_值;
//具体接口实现
对象字段。值
{
收到
{
返回_值;
}
}
公共价值
{
收到
{
返回_值;
}
}
}
旁注:为什么将字段\u值作为公共值?这违背了封装字段的目的。。。C#编译器爱你,希望你安全高效,因此有时它会阻止你做危险的、没有效率的事情。就像你妈妈不让你在屋顶上骑自行车一样,即使那会很棒。List
没有什么特别之处。它是一个普通类,由对编译器内部没有特殊访问权限的人编写,编译器对它没有任何特殊的处理。如果你想知道List
的作者是如何实现IList
的,你可以阅读源代码。它被调用了,正如你所看到的,它既不是特别的,也不是未提及的。我投票结束这个问题,因为“”OP说他的限制之一是接口不能支持Generics,那么Field接口将不得不扩展Field,这将导致相同的编译错误。好消息是,它可以编译!!!但它污染了我的命名空间。尝试使用这两种方法会导致:错误CS0102:“字段”已包含“值”的定义!我删除了我的答案,这是更好的+1.使用new
标记字段
版本的值
,表明隐藏是有意的,这是一种很好的方式。为什么字段接口继承自字段?用MyField:Field,Field代替会更好吗?那么你就不会隐藏遗产了。@Nyranith:这可能会更好,但这不是因为任何“隐藏”遗产。相反:Field
的作者通过继承Field
,要求实现接口的所有类都实现Value
的两个版本,这既麻烦又烦人。但是,请注意,在基类库中,IEnumerator
确实从IEnumerator
中插入,因此这种事情确实有一些先例。您很接近,我希望MyTypedValue也与Value方法共享相同的名称
public class Field<T> : Field
{
T _value;
//specific interface implementation
object Field.Value
{
get
{
return _value;
}
}
public T Value
{
get
{
return _value;
}
}
}