添加Lesson17
This commit is contained in:
@@ -69,6 +69,10 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson16_List排序", "Less
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson16_List排序练习", "Lesson16_List排序练习\Lesson16_List排序练习.csproj", "{D6D1193A-668E-454A-BFBF-6186A2C76509}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson17_协变逆变", "Lesson17_协变逆变\Lesson17_协变逆变.csproj", "{123A2A95-0776-4C76-8570-4D879159D362}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson17_协变逆变练习", "Lesson17_协变逆变练习\Lesson17_协变逆变练习.csproj", "{DDF7EBE2-4B8E-4B48-97BC-06EB4E55796A}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -207,6 +211,14 @@ Global
|
||||
{D6D1193A-668E-454A-BFBF-6186A2C76509}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D6D1193A-668E-454A-BFBF-6186A2C76509}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D6D1193A-668E-454A-BFBF-6186A2C76509}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{123A2A95-0776-4C76-8570-4D879159D362}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{123A2A95-0776-4C76-8570-4D879159D362}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{123A2A95-0776-4C76-8570-4D879159D362}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{123A2A95-0776-4C76-8570-4D879159D362}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{DDF7EBE2-4B8E-4B48-97BC-06EB4E55796A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{DDF7EBE2-4B8E-4B48-97BC-06EB4E55796A}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{DDF7EBE2-4B8E-4B48-97BC-06EB4E55796A}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{DDF7EBE2-4B8E-4B48-97BC-06EB4E55796A}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,86 @@
|
||||
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修饰的 泛型委托 可以相互装载(有父子关系的泛型)
|
||||
// 协变 父类泛型委托装子类泛型委托 逆变 子类泛型委托装父类泛型委托
|
||||
@@ -0,0 +1,10 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,53 @@
|
||||
namespace Lesson17_协变逆变练习
|
||||
{
|
||||
//协变
|
||||
delegate T TestOut<out T>();
|
||||
//逆变
|
||||
delegate void TestIn<in T>(T t);
|
||||
|
||||
class Father
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
class Son : Father
|
||||
{
|
||||
|
||||
}
|
||||
internal class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
#region 练习题一
|
||||
//请简述协变逆变有什么作用
|
||||
|
||||
//协变逆变是用来修饰泛型替代符的 只存在于泛型接口和泛型委托中
|
||||
//1.协变 用 out 修饰 只能作为返回值 不能作为参数
|
||||
//2.逆变 用 in 修饰 只能作为参数 不能作为返回值
|
||||
|
||||
//遵循里氏替换原则 用out和in修饰的泛型委托如果类型是父子关系 那么可以相互装载
|
||||
// 协变:父类泛型委托变量 可以装 子类泛型委托实例
|
||||
// 逆变:子类泛型委托变量 可以装 父类泛型委托实例
|
||||
#endregion
|
||||
|
||||
#region 练习题二
|
||||
//请写出协变逆变的代码示例
|
||||
|
||||
TestOut<Son> s = () =>
|
||||
{
|
||||
return new Son();
|
||||
};
|
||||
|
||||
TestOut<Father> tf = s;
|
||||
Father f = tf();
|
||||
|
||||
TestIn<Father> iF = (value) =>
|
||||
{
|
||||
Console.WriteLine("接受到一个Father类型的参数");
|
||||
};
|
||||
TestIn<Son> iS = iF;
|
||||
iS(new Son());
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user