【问题标题】:Invalid variance: The type parameter 'T' must be contravariantly valid on 'UserQuery.IItem<T>.ItemList'. 'T' is covariant [duplicate]无效方差:类型参数“T”必须在“UserQuery.IItem<T>.ItemList”上逆变有效。 'T'是协变的[重复]
【发布时间】:2012-09-18 20:36:14
【问题描述】:

为什么方法可以编译时属性报错?

public interface IFoo {}
public interface IBar<out T> where T : IFoo {}

public interface IItem<out T> where T: IFoo
{
    // IEnumerable<IBar<T>> GetList(); // works
    IEnumerable<IBar<T>> ItemList { get; set; } // Error!
}

错误:

无效方差:类型参数“T”必须是逆变有效的 在“UserQuery.IItem.ItemList”上。 'T' 是协变的。

【问题讨论】:

    标签: c# covariance


    【解决方案1】:

    您收到编译器错误,因为您有一个属性 getter (get) 和一个 setter (set)。属性 getter 在其输出中包含 T,因此 out 有效,但属性设置器将在其输入中包含 T,因此它需要 in 修饰符。

    因为你在T 上有out,你需要删除setter,它会编译:

    public interface IItem<out T> where T : IFoo
    {
        // IEnumerable<IBar<T>> GetList(); // works
        IEnumerable<IBar<T>> ItemList { get; } // also works
    }
    

    如果您的 Tin 通用参数,则以下内容将起作用:

    public interface IItem<in T> where T : IFoo
    {
        IEnumerable<IBar<T>> ItemList { set; } 
    }
    

    但是您不能同时拥有两者 (out,in),因此您不能拥有带有 getter 和 setter 的协/逆变属性。

    【讨论】:

    • 我不明白这个。你已经关联了,获取,设置。为什么我不能使用 out,因为 out 仅表示“此类型或任何派生类型。”。如果 B 派生自 A,那么为什么我不能将 B 传递给需要输出 A 的接口上的任何属性,因为无论如何 B 只会像 A 一样被调用。问题是什么,与这些有什么关系? in 表示“这种类型或任何基本类型”。我不希望这样,因为我希望至少使用 A 的行为集,传递“a”不会削减它。所以我不想“进入”......但我确实希望能够将 B 设置为 A。
    【解决方案2】:

    不允许使用 setter,因为如果是,您将能够这样做:

    public interface ISubFoo : IFoo { }
    
    IItem<ISubFoo> item = //whatever
    item.ItemList = new List<IBar<IFoo>>>();
    

    这不是类型安全的。

    【讨论】:

      猜你喜欢
      • 2011-06-29
      • 2022-08-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-23
      相关资源
      最近更新 更多