c#对象接口返回类型协方差

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 {

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
      {
         return _value;
      }
   }
}
公共接口字段
{
对象值{get;}
}
公共类MyField:Field
{
T_值;
公共价值
{
收到
{
返回_值;
}
}
}
为什么??List在microsoft类中扩展List,但我作为用户(复制相同的设计模式)不允许这样做?为什么?

尝试T:object也会出现编译器错误

我该如何解决这个问题

关于同一主题的其他1.000.000条线程,例如:
废话,“返回类型协方差”,废话,“你不能”

他们没有就如何编译这个beast提出解决方案或解决方法。 要求:
1) 字段是不能接受泛型的接口。被称为“统一”的邪恶框架禁止泛型。

2) “implements Field”(实现字段)的字段具有泛型T.

您在界面中不使用模板类型,而是使用对象。请尝试以下操作:

 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;
      }
   }
}