in和out用在范型interface和delegate中, 用来支持逆变和协变(in是逆变,out是协变)。协变保留赋值兼容性,逆变与之相反。
下例中,泛型接口类型参数T有out修饰符,所以
a) 支持协变,ITest<Base> b = new D(); 可以编译通过,而ITest<Derive> d = new B();出错;
b) T类型只能用过函数返回值,故 T GetInstance(); 编译通过,而 void ShowMe(T obj); 出错;
如果是改为in修饰符,则支持逆变,上述情况相反!
in和out泛型修饰符只能用在泛型接口和泛型委托里面,这样的泛型接口和泛型委托称为变体。
class Base
{
}
class Derive : Base
{
}
interface ITest<out T>
{
T GetInstance();
<span style="white-space:pre"> </span>void ShowMe(T obj);
}
class D : ITest<Derive>
{
}
class B : ITest<Base>
{
}
class Program
{
private static void Main(string[] args)
{
ITest<Derive> d = new B();
ITest<Base> b = new D();
}
}
.Net中典型的变体:
public delegate TResult Func<out TResult>();// TResult类型是返回值类型
public delegate TResult Func<in T, out TResult>(T arg); //输入类型T,返回类型TResult
public interface IEnumerable<out T> : IEnumerable // T只出现在返回类型中
public interface IEnumerator<out T> : IDisposable, IEnumerator
public class List<T> : IList<T>, ICollection<T>, IList, ICollection, IReadOnlyList<T>, IReadOnlyCollection<T>, IEnumerable<T>, IEnumerable // 实现变体接口IEnumerable<T>
public class Queue<T> : IEnumerable<T>, ICollection, IEnumerable // 实现变体接口 IEnumerable<T>