28

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

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<T>.ItemList”上逆变有效。“T”是协变的。

4

2 回答 2

39

您会收到编译器错误,因为您有一个属性 getter ( get) 和一个 setter ( set)。属性 getterT的输出中有 in ,所以out可以工作,但是属性 setterT的输入中有 in ,所以它需要in修饰符。

因为你有outT需要删除设置器,它会编译:

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 的协/逆变属性。

于 2012-09-18T20:42:38.883 回答
2

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

public interface ISubFoo : IFoo { }

IItem<ISubFoo> item = //whatever
item.ItemList = new List<IBar<IFoo>>>();

这不是类型安全的。

于 2012-09-18T20:52:24.510 回答