Generics 协方差和逆变:如何在同一界面中使用两者?
如何在接口中的泛型类型上使用out参数,并将此类型重用为方法的参数,或作为非协变函数的返回 请参阅示例(我的真实案例是“添加(T项)”,其他是测试):Generics 协方差和逆变:如何在同一界面中使用两者?,generics,interface,covariance,contravariance,variance,Generics,Interface,Covariance,Contravariance,Variance,如何在接口中的泛型类型上使用out参数,并将此类型重用为方法的参数,或作为非协变函数的返回 请参阅示例(我的真实案例是“添加(T项)”,其他是测试): 公共接口ITestAdapter { void Clear();//编译 T GetItemAt(int索引);//编译 void Add(T项);//错误:变量无效:类型参数“T”在“ITestAdapter.Add(T)”上必须相反地有效。“T”是协变的。 IList GetInnerList();//错误:变量无效:类型参数“T”在“ite
公共接口ITestAdapter
{
void Clear();//编译
T GetItemAt(int索引);//编译
void Add(T项);//错误:变量无效:类型参数“T”在“ITestAdapter.Add(T)”上必须相反地有效。“T”是协变的。
IList GetInnerList();//错误:变量无效:类型参数“T”在“iteStatAdapter.GetInnerList()”上必须始终有效。“T”是协变的。
IEnumerable GetInnerAsEnumerable();//编译
}
公共类测试适配器:ITestAdapter
{
公共测试适配器(IList innerList)
{
这。_innerList=innerList;
}
私有只读IList\u innerList;
公共空间清除()
{
此._innerList.Clear();
}
公共作废新增(T项)
{
此._innerList.Add(项);
}
公共T GetItemAt(整数索引)
{
返回此。_innerList[索引];
}
公共IList GetInnerList()
{
返回此。\u innerList;
}
public IEnumerable GetInnerAsEnumerable()
{
返回此。\u innerList;
}
}
公共A类{}
公共类AB:A{}
公开课考试
{
公共静态无效Doy()
{
var list=新列表();
var typed=新约适配器(列表);
var boxed=默认值(ITestAdapter);
boxed=typed;//确定;
}
}
可能与GetInnerList()不完全相同,正如您在我的示例中看到的那样;这只是一个测试,解决方案(GetInnerAsEnumerable())与您引用的文章中的解决方案相同。在我的例子中,我想使用泛型类型作为参数(Add()方法)。推理是一样的。因为类型是逆变的,所以不能将其用作“输入”。这里有一个更好的解释:可能与GetInnerList()不完全相同,正如您在我的示例中看到的那样;这只是一个测试,解决方案(GetInnerAsEnumerable())与您引用的文章中的解决方案相同。在我的例子中,我想使用泛型类型作为参数(Add()方法)。推理是一样的。因为类型是逆变的,所以不能将其用作“输入”。更好的解释是:
public interface ITestAdapter<out T>
{
void Clear(); // Compile
T GetItemAt(int index); // Compile
void Add(T item); // ERROR: Invalid variance: The type parameter 'T' must be contravariantly valid on 'ITestAdapter<T>.Add(T)'. 'T' is covariant.
IList<T> GetInnerList(); //ERROR: Invalid variance: The type parameter 'T' must be invariantly valid on 'ITestAdapter<T>.GetInnerList()'. 'T' is covariant.
IEnumerable<T> GetInnerAsEnumerable(); // Compile
}
public class TestAdapter<T> : ITestAdapter<T>
{
public TestAdapter(IList<T> innerList)
{
this._innerList = innerList;
}
private readonly IList<T> _innerList;
public void Clear()
{
this._innerList.Clear();
}
public void Add(T item)
{
this._innerList.Add(item);
}
public T GetItemAt(int index)
{
return this._innerList[index];
}
public IList<T> GetInnerList()
{
return this._innerList;
}
public IEnumerable<T> GetInnerAsEnumerable()
{
return this._innerList;
}
}
public class A { }
public class AB : A { }
public class Test
{
public static void Doy()
{
var list = new List<AB>();
var typed = new TestAdapter<AB>(list);
var boxed = default(ITestAdapter<A>);
boxed = typed; // OK;
}
}