86 lines
2.4 KiB
C#
86 lines
2.4 KiB
C#
namespace Lesson17_协变逆变
|
|
{
|
|
#region 知识点一 什么是协变逆变
|
|
//协变:
|
|
//和谐的变化,自然的变化
|
|
//因为 里氏替换原则 父类可以装子类
|
|
//所以 子类变父类
|
|
//比如 string 变 object
|
|
//感受是和谐的
|
|
|
|
//逆变:
|
|
//逆常规的变化,不正常的变化
|
|
//因为 里氏替换原则 父类可以装子类 但子类不能装父类
|
|
//所以 父类变子类
|
|
//比如 object 变 string
|
|
//感受是不正常的
|
|
|
|
//协变和逆变是用来修饰泛型的
|
|
//协变:out
|
|
//逆变:in
|
|
//用于在泛型中 修饰 泛型字母
|
|
//只有泛型接口和泛型委托能使用
|
|
#endregion
|
|
|
|
#region 知识点二 作用
|
|
//1.返回值 和 参数
|
|
//用 out 修饰的泛型 只能作为返回值 不能作为参数
|
|
delegate T TestOut<out T>();
|
|
//用 in 修饰的泛型 只能作为参数 不能作为返回值
|
|
delegate void TestIn<in T>(T t);
|
|
//注意:只能在泛型接口和泛型委托中使用
|
|
|
|
interface Test<in T,out T2>
|
|
{
|
|
void TestFun(T v);
|
|
T2 TestFun2();
|
|
}
|
|
|
|
|
|
|
|
|
|
//2.结合里氏替换原则理解
|
|
|
|
class Father
|
|
{
|
|
|
|
}
|
|
|
|
class Son : Father
|
|
{
|
|
|
|
}
|
|
#endregion
|
|
internal class Program
|
|
{
|
|
static void Main(string[] args)
|
|
{
|
|
#region 知识点三 (结合里氏替换原则)
|
|
//协变:子类变父类
|
|
TestOut<Son> os = () =>
|
|
{
|
|
return new Son();
|
|
};
|
|
TestOut<Father> of = os;//不能直接装,TestOut必须通过协变的方式才能装os
|
|
Father f = of();//实际返回的是Son类型的对象
|
|
|
|
//逆变:父类变子类
|
|
TestIn<Father> iF = (value) =>
|
|
{
|
|
|
|
};
|
|
TestIn<Son> iS = iF;//不能直接装,TestIn必须通过逆变的方式才能装iF
|
|
iS(new Son());//实际传递进去的是Father类型的对象
|
|
#endregion
|
|
}
|
|
}
|
|
}
|
|
//总结
|
|
//协变 out
|
|
//逆变 in
|
|
//用来修饰 泛型替代符的 只能修饰接口和委托中的泛型
|
|
|
|
//作用两点
|
|
//1.out修饰的泛型类型 只能作为返回值类型 in修饰的泛型类型 只能作为 参数类型
|
|
//2.遵循里氏替换原则的 用out和in修饰的 泛型委托 可以相互装载(有父子关系的泛型)
|
|
// 协变 父类泛型委托装子类泛型委托 逆变 子类泛型委托装父类泛型委托 |