C# 无效差异:类型参数';T';必须在';UserQuery.IItem<;T>;。项目列表'';T';是协变的
为什么属性在方法可以编译时得到错误C# 无效差异:类型参数';T';必须在';UserQuery.IItem<;T>;。项目列表'';T';是协变的,c#,covariance,C#,Covariance,为什么属性在方法可以编译时得到错误 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>> Item
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!
}
公共接口IFoo{}
公共接口IBar,其中T:IFoo{}
公共接口项,其中T:IFoo
{
//IEnumerable GetList();//有效
IEnumerable ItemList{get;set;}//错误!
}
错误:
无效差异:类型参数“T”必须是反向有效的
在“UserQuery.IItem.ItemList”上T’是协变的
您得到编译器错误是因为您有一个属性getter(
get
)和一个setter(set
)。属性getter的输出中有T
,因此out
可以工作,但属性setter的输入中将有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
}
但是您不能同时拥有两个(
out,in
),因此您不能拥有具有getter和setter的co/conversative属性。不允许使用setter,因为如果是这样,您可以执行以下操作:
public interface ISubFoo : IFoo { }
IItem<ISubFoo> item = //whatever
item.ItemList = new List<IBar<IFoo>>>();
公共接口ISubFoo:IFoo{}
IItem item=//随便什么
item.ItemList=新列表>();
这是不安全的。我不明白这一点。你已经联系了出去,进去,集合。为什么我不能使用out,因为out只是指“这个类型或任何派生类型”。如果B派生自A,那么为什么我不能将B传递给接口上需要A out A的任何属性,因为无论如何,B只能像A一样被调用。这是什么问题?这与我们有什么关系?in表示“此类型或任何基本类型”。我不希望这样,因为我希望至少使用A的行为集,传递“A”不会减少它。所以我不想“进去”…但我确实希望能够将B设置为A。
public interface ISubFoo : IFoo { }
IItem<ISubFoo> item = //whatever
item.ItemList = new List<IBar<IFoo>>>();