一.概念
协变:
和谐的变化
如里氏替换原则中的父类装子类,用object类装string
逆变:
逆常规的变化
如父类变子类,object变string
协变和逆变是用来修饰泛型的
协变out
逆变in
用于泛型中修饰泛型字母,只有泛型接口和泛型委托能用
二.作用
用out修饰的泛型只能作为返回值
用in修饰的泛型只能作为参数
//用out修饰的泛型不能作为参数
//delegate T TestOut<out T>(T t);//错误!用out修饰的T不能作为参数
//用in修饰的泛型不能作为返回值
//delegate T TestIn<in T>(T t);//错误!T不能作为返回类型
//只能接口和委托类型使用变型修饰符
//class TestClass<in T>
//{
// //错误!类不能使用变型修饰符
//}
interface Test<out T>
{
T TestFun();
}
结合里氏替换原则理解
class Father
{
}
class Son : Father
{
}
delegate T TestOut<out T>();
delegate void TestIn<in T>(T t);
//使用时
TestOut<Son> os = () =>
{
return new Son();
};
//注意若委托T没加out修饰符,则不能这样替换,因为委托格式不同
//若加上out则可以,看起来像父类装子类 -> 协变
TestOut<Father> of = os;
Father f = of();//实际f是Son
//Son f = of();//错误!与委托格式不匹配
TestIn<Father> iF = (value) =>
{
};
//若委托泛型没有in,则会报错!
//这样看起来像子类装父类 -> 逆变
TestIn<Son> iS = iF;
iS(new Son());//虽然传了Son类型,实际上调用了iF
总结:
协变out,逆变in
协变 父类泛型委托装子类泛型委托
逆变 子类泛型委托装父类泛型委托
资料来源<唐老狮C#教程>