Compare commits
10 Commits
301c345a6a
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
| 7ca83872f3 | |||
| ed22d4bcbd | |||
| 0fa8be7459 | |||
| f77c10f1d5 | |||
| a79f6fcf42 | |||
| faee796928 | |||
| b1d4959956 | |||
| b4d3ced472 | |||
| be8eb0f422 | |||
| 657a23e681 |
+132
@@ -49,6 +49,50 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson11_泛型栈和队列
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson11_泛型栈和队列练习", "Lesson11_泛型栈和队列练习\Lesson11_泛型栈和队列练习.csproj", "{C91DDD1F-E702-430F-95FA-22BBEDE5E011}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson12_委托", "Lesson12_委托\Lesson12_委托.csproj", "{43FC89B7-F926-4036-93E7-C88746BC49F0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson12_委托练习", "Lesson12_委托练习\Lesson12_委托练习.csproj", "{A5EDC63B-0ACF-48FF-BABC-8C4D1B0E12D9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson13_事件", "Lesson13_事件\Lesson13_事件.csproj", "{66C78CE0-E022-4E59-8EB4-C469957AA5D9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson13_事件练习", "Lesson13_事件练习\Lesson13_事件练习.csproj", "{AD35AAD1-3AEE-4A8D-95EB-AA3DAE7776E0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson14_匿名函数", "Lesson14_匿名函数\Lesson14_匿名函数.csproj", "{10AB400D-490A-49B1-9ABF-3993EE0B49E0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson14_匿名函数练习", "Lesson14_匿名函数练习\Lesson14_匿名函数练习.csproj", "{9030BA7A-FDFA-4F88-869E-918589104831}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson15_lambda表达式", "Lesson15_lambad表达式\Lesson15_lambda表达式.csproj", "{50810F24-0145-43C6-AE3E-1D99D0583AB8}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson15_lambda表达式练习", "Lesson15_lambad表达式练习\Lesson15_lambda表达式练习.csproj", "{E0931580-D76C-4434-B059-149AEED828ED}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson16_List排序", "Lesson16_List排序\Lesson16_List排序.csproj", "{8417820B-342A-423C-9865-29784EB5F4A6}"
|
||||
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
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson18_多线程", "Lesson18_多线程\Lesson18_多线程.csproj", "{90769697-6F30-4BB0-A74E-3C3A9BDD8669}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson18_多线程练习", "Lesson18_多线程练习\Lesson18_多线程练习.csproj", "{D98DCA4D-7F46-4376-9BBF-F1343D058FF3}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson19_预处理器指令", "Lesson19_预处理器指令\Lesson19_预处理器指令.csproj", "{B8C4D4E0-7249-4AF7-BA24-18739B80D4A9}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson19_预处理器指令练习", "Lesson19_预处理器指令练习\Lesson19_预处理器指令练习.csproj", "{61DA81E2-A8D8-480E-B708-3D28334D76B0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson20_反射", "Lesson20_反射概念和关键类Type\Lesson20_反射.csproj", "{1C0205AE-A49E-405D-A797-A0D2B6C37895}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "测试类库", "测试类库\测试类库.csproj", "{70C2E0D7-1F4A-4442-AF1C-3B1C2475B748}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson20_反射练习", "Lesson20_反射练习\Lesson20_反射练习.csproj", "{A93B1D1E-1A4D-47CB-AA26-2D08B3E557F1}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "反射练习库", "反射练习库\反射练习库.csproj", "{86839643-1A23-454E-8B06-839900B3E032}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson21_特性", "Lesson21_特性\Lesson21_特性.csproj", "{806658BC-2943-461C-BD60-D3B51F0BA223}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Lesson21_特性练习", "Lesson21_特性练习\Lesson21_特性练习.csproj", "{5C3AFDDF-23DF-4C9E-8335-42DB430D2EE4}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -147,6 +191,94 @@ Global
|
||||
{C91DDD1F-E702-430F-95FA-22BBEDE5E011}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C91DDD1F-E702-430F-95FA-22BBEDE5E011}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C91DDD1F-E702-430F-95FA-22BBEDE5E011}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{43FC89B7-F926-4036-93E7-C88746BC49F0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{43FC89B7-F926-4036-93E7-C88746BC49F0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{43FC89B7-F926-4036-93E7-C88746BC49F0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{43FC89B7-F926-4036-93E7-C88746BC49F0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A5EDC63B-0ACF-48FF-BABC-8C4D1B0E12D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A5EDC63B-0ACF-48FF-BABC-8C4D1B0E12D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A5EDC63B-0ACF-48FF-BABC-8C4D1B0E12D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A5EDC63B-0ACF-48FF-BABC-8C4D1B0E12D9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{66C78CE0-E022-4E59-8EB4-C469957AA5D9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{66C78CE0-E022-4E59-8EB4-C469957AA5D9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{66C78CE0-E022-4E59-8EB4-C469957AA5D9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{66C78CE0-E022-4E59-8EB4-C469957AA5D9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AD35AAD1-3AEE-4A8D-95EB-AA3DAE7776E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AD35AAD1-3AEE-4A8D-95EB-AA3DAE7776E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AD35AAD1-3AEE-4A8D-95EB-AA3DAE7776E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AD35AAD1-3AEE-4A8D-95EB-AA3DAE7776E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{10AB400D-490A-49B1-9ABF-3993EE0B49E0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{10AB400D-490A-49B1-9ABF-3993EE0B49E0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{10AB400D-490A-49B1-9ABF-3993EE0B49E0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{10AB400D-490A-49B1-9ABF-3993EE0B49E0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{9030BA7A-FDFA-4F88-869E-918589104831}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{9030BA7A-FDFA-4F88-869E-918589104831}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{9030BA7A-FDFA-4F88-869E-918589104831}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{9030BA7A-FDFA-4F88-869E-918589104831}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{50810F24-0145-43C6-AE3E-1D99D0583AB8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{50810F24-0145-43C6-AE3E-1D99D0583AB8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{50810F24-0145-43C6-AE3E-1D99D0583AB8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{50810F24-0145-43C6-AE3E-1D99D0583AB8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E0931580-D76C-4434-B059-149AEED828ED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E0931580-D76C-4434-B059-149AEED828ED}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E0931580-D76C-4434-B059-149AEED828ED}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E0931580-D76C-4434-B059-149AEED828ED}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{8417820B-342A-423C-9865-29784EB5F4A6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{8417820B-342A-423C-9865-29784EB5F4A6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{8417820B-342A-423C-9865-29784EB5F4A6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{8417820B-342A-423C-9865-29784EB5F4A6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D6D1193A-668E-454A-BFBF-6186A2C76509}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{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
|
||||
{90769697-6F30-4BB0-A74E-3C3A9BDD8669}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{90769697-6F30-4BB0-A74E-3C3A9BDD8669}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{90769697-6F30-4BB0-A74E-3C3A9BDD8669}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{90769697-6F30-4BB0-A74E-3C3A9BDD8669}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{D98DCA4D-7F46-4376-9BBF-F1343D058FF3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{D98DCA4D-7F46-4376-9BBF-F1343D058FF3}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{D98DCA4D-7F46-4376-9BBF-F1343D058FF3}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{D98DCA4D-7F46-4376-9BBF-F1343D058FF3}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B8C4D4E0-7249-4AF7-BA24-18739B80D4A9}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B8C4D4E0-7249-4AF7-BA24-18739B80D4A9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B8C4D4E0-7249-4AF7-BA24-18739B80D4A9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B8C4D4E0-7249-4AF7-BA24-18739B80D4A9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{61DA81E2-A8D8-480E-B708-3D28334D76B0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{61DA81E2-A8D8-480E-B708-3D28334D76B0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{61DA81E2-A8D8-480E-B708-3D28334D76B0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{61DA81E2-A8D8-480E-B708-3D28334D76B0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{1C0205AE-A49E-405D-A797-A0D2B6C37895}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{1C0205AE-A49E-405D-A797-A0D2B6C37895}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{1C0205AE-A49E-405D-A797-A0D2B6C37895}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{1C0205AE-A49E-405D-A797-A0D2B6C37895}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{70C2E0D7-1F4A-4442-AF1C-3B1C2475B748}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{70C2E0D7-1F4A-4442-AF1C-3B1C2475B748}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{70C2E0D7-1F4A-4442-AF1C-3B1C2475B748}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{70C2E0D7-1F4A-4442-AF1C-3B1C2475B748}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{A93B1D1E-1A4D-47CB-AA26-2D08B3E557F1}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{A93B1D1E-1A4D-47CB-AA26-2D08B3E557F1}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{A93B1D1E-1A4D-47CB-AA26-2D08B3E557F1}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A93B1D1E-1A4D-47CB-AA26-2D08B3E557F1}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{86839643-1A23-454E-8B06-839900B3E032}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{86839643-1A23-454E-8B06-839900B3E032}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{86839643-1A23-454E-8B06-839900B3E032}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{86839643-1A23-454E-8B06-839900B3E032}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{806658BC-2943-461C-BD60-D3B51F0BA223}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{806658BC-2943-461C-BD60-D3B51F0BA223}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{806658BC-2943-461C-BD60-D3B51F0BA223}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{806658BC-2943-461C-BD60-D3B51F0BA223}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{5C3AFDDF-23DF-4C9E-8335-42DB430D2EE4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{5C3AFDDF-23DF-4C9E-8335-42DB430D2EE4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{5C3AFDDF-23DF-4C9E-8335-42DB430D2EE4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{5C3AFDDF-23DF-4C9E-8335-42DB430D2EE4}.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,25 @@
|
||||
namespace ConsoleApp1
|
||||
{
|
||||
class shopItem
|
||||
{
|
||||
public int price;
|
||||
|
||||
public shopItem(int price)
|
||||
{
|
||||
this.price = price;
|
||||
}
|
||||
|
||||
}
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
List<shopItem> shopItems = new List<shopItem>();//创建一个List来存放商店物品
|
||||
shopItems.Add(new shopItem(3));//往List中添加每个物品的价格
|
||||
shopItems.Add(new shopItem(1));
|
||||
shopItems.Add(new shopItem(2));
|
||||
|
||||
shopItems.Sort((a, b) => { return a.price > b.price ? 1 : -1; });//使用Sort方法对List进行排序,按照价格从低到高排序
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,178 @@
|
||||
namespace Lesson12_委托
|
||||
{
|
||||
#region 知识点一 委托是什么
|
||||
//委托是函数的容器
|
||||
//可以理解为表示函数(方法)的变量类型
|
||||
//用来 存储、传递函数
|
||||
//委托的本质是一个类,用来定义函数(方法)的类型(返回值和参数的类型)
|
||||
//不同的 函数必须对应和自己格式一致的委托
|
||||
#endregion
|
||||
|
||||
#region 知识点二 基本语法
|
||||
//关键字:delegate
|
||||
//语法:访问修饰符 delegate 返回值 委托名(参数列表);
|
||||
|
||||
//写在哪里?
|
||||
//可以在namespace的class语句种
|
||||
//更多写在namespace种
|
||||
|
||||
//简单记忆委托语法就是 函数声明语法前加一个delegate关键字
|
||||
#endregion
|
||||
|
||||
#region 知识点三 定义自定义委托
|
||||
//访问修饰符不写 默认为public在别的命名空间中也能使用
|
||||
//private其他命名空间就用不了了
|
||||
//但一般使用public
|
||||
|
||||
delegate void MyFun();
|
||||
|
||||
delegate int MyFun2(int a);
|
||||
#endregion
|
||||
|
||||
#region 知识点四 使用定义好的委托
|
||||
//委托变量是函数的容器
|
||||
|
||||
//委托常用在:
|
||||
//1.作为类的成员
|
||||
//2.作为函数的参数
|
||||
class Test
|
||||
{
|
||||
public MyFun fun;
|
||||
public MyFun2 fun2;
|
||||
|
||||
public void TestFun(MyFun f, MyFun2 f2)
|
||||
{
|
||||
//一般是先处理一些别的逻辑 当这些逻辑处理完毕后 再调用传递进来的函数
|
||||
|
||||
f();
|
||||
Console.WriteLine(f2(123));
|
||||
this.fun = f;
|
||||
this.fun2 = f2;
|
||||
}
|
||||
|
||||
public void AddFun(MyFun fun,MyFun2 fun2)
|
||||
{
|
||||
this.fun += fun;
|
||||
this.fun2 += fun2;
|
||||
}
|
||||
|
||||
public void RemoveFun(MyFun fun, MyFun2 fun2)
|
||||
{
|
||||
this.fun -= fun;
|
||||
this.fun2 -= fun2;
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 知识点五 委托变量可以存储多个函数
|
||||
//上方的例子已经演示
|
||||
#endregion
|
||||
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("委托");
|
||||
|
||||
MyFun f = new MyFun(Fun);
|
||||
Console.WriteLine("别的逻辑操作");
|
||||
f.Invoke();//调用委托变量存储的函数
|
||||
|
||||
MyFun f2 = Fun;//简写
|
||||
Console.WriteLine("别的逻辑操作");
|
||||
f2();
|
||||
|
||||
//MyFun f2 = Fun2;//格式错误 不同格式的函数不能存储到同一个委托变量中
|
||||
MyFun2 f21 = Fun2;
|
||||
Console.WriteLine(f21(123));
|
||||
|
||||
MyFun2 f22 = new MyFun2(Fun2);
|
||||
Console.WriteLine(f22.Invoke(123));
|
||||
|
||||
Test t = new Test();
|
||||
t.TestFun(Fun, Fun2);
|
||||
|
||||
|
||||
Console.WriteLine("____________________");
|
||||
//如何用委托存储多个函数
|
||||
MyFun ff = Fun;
|
||||
ff += Fun3;//多加了Fun3,所以会调用两个函数
|
||||
ff();
|
||||
//完全写法是
|
||||
ff = ff + Fun;
|
||||
|
||||
Console.WriteLine("____________________");
|
||||
t.AddFun(Fun, Fun2);
|
||||
t.fun();
|
||||
t.fun2(123);
|
||||
|
||||
Console.WriteLine("____________________");
|
||||
ff = null;
|
||||
ff += Fun;
|
||||
ff += Fun3;
|
||||
ff();
|
||||
Console.WriteLine("执行删除后:");
|
||||
ff -= Fun;
|
||||
ff();
|
||||
ff -= Fun;//多删不会报错但也无效
|
||||
|
||||
|
||||
#region 知识点六 系统定义好的委托
|
||||
Console.WriteLine("____________________");
|
||||
//Action 没有返回值的委托,需要引用的命名空间 System
|
||||
Action a = Fun;
|
||||
//之前的操作也可以用
|
||||
a += Fun3;
|
||||
a();
|
||||
|
||||
Console.WriteLine("____________________");
|
||||
//Func<> 有返回值的委托,最后一个类型参数是返回值类型,前面的类型参数是参数类型
|
||||
Func<string> funcString = Fun4;
|
||||
//Func<int> funcInt = xxxx;
|
||||
|
||||
//可以传n个参数的 系统提供了 1到16个参数的Func<> 直接使用
|
||||
Action<int, string> a2 = Fun6;
|
||||
|
||||
//Action用来存储没有返回值的函数
|
||||
//Func用来存储有返回值的函数
|
||||
//两个委托都可以以泛型方式同时存储多个函数
|
||||
#endregion
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static void Fun()
|
||||
{
|
||||
Console.WriteLine("这是Fun()函数");
|
||||
}
|
||||
static void Fun3()
|
||||
{
|
||||
Console.WriteLine("这是Fun3()函数");
|
||||
}
|
||||
static string Fun4()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
static void Fun6(int i,string s)
|
||||
{
|
||||
|
||||
}
|
||||
static int Fun2(int a)
|
||||
{
|
||||
return a;
|
||||
}
|
||||
}
|
||||
}
|
||||
//总结
|
||||
//委托是函数的容器
|
||||
//可以用 委托变量 来存储、传递函数
|
||||
//系统提供了 Action 和 Func 两个通用委托
|
||||
//Action:没有返回值 参数数量0~16个
|
||||
//Func:有返回值 参数数量0~16个(最后一个类型参数是返回值类型)
|
||||
@@ -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,117 @@
|
||||
namespace Lesson12_委托练习
|
||||
{
|
||||
#region 第一题
|
||||
abstract class Person()
|
||||
{
|
||||
public abstract void Eating();
|
||||
}
|
||||
|
||||
class Mother : Person
|
||||
{
|
||||
public Action beginEat;
|
||||
|
||||
public void Cooking()
|
||||
{
|
||||
Console.WriteLine("妈妈做饭");
|
||||
if (beginEat != null)
|
||||
{
|
||||
beginEat();
|
||||
}
|
||||
}
|
||||
public override void Eating()
|
||||
{
|
||||
Console.WriteLine("妈妈吃饭");
|
||||
|
||||
}
|
||||
}
|
||||
class Father : Person
|
||||
{
|
||||
public override void Eating()
|
||||
{
|
||||
Console.WriteLine("爸爸吃饭");
|
||||
}
|
||||
}
|
||||
class Son : Person
|
||||
{
|
||||
public override void Eating()
|
||||
{
|
||||
Console.WriteLine("孩子吃饭");
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
class Monster
|
||||
{
|
||||
//当怪物死亡时,把自己作为参数传出去
|
||||
public Action<Monster> deadDoSomething;
|
||||
public int money = 10;
|
||||
public void Dead()
|
||||
{
|
||||
Console.WriteLine("怪物死亡");
|
||||
if (deadDoSomething != null)
|
||||
{
|
||||
deadDoSomething(this);
|
||||
}
|
||||
|
||||
deadDoSomething = null;//清空所需要做的事情(在这里就是怪物的击杀奖励已经领取了不要重复刷
|
||||
//一般有加就有减
|
||||
}
|
||||
}
|
||||
class Player
|
||||
{
|
||||
private int money = 0;
|
||||
public void MonsterDeadDoSomething(Monster m)
|
||||
{
|
||||
this.money += m.money;
|
||||
Console.WriteLine("玩家获得了" + m.money + "金币");
|
||||
}
|
||||
}
|
||||
class Panel
|
||||
{
|
||||
private int showNowMoney = 0;
|
||||
public void MonsterDeadDoSomething(Monster m)
|
||||
{
|
||||
this.showNowMoney += m.money;
|
||||
Console.WriteLine("面板显示当前金币" + showNowMoney);
|
||||
}
|
||||
}
|
||||
class Achievement
|
||||
{
|
||||
private int nowKillMonsterNum = 0;
|
||||
public void MonsterDeadDoSomething(Monster m)
|
||||
{
|
||||
nowKillMonsterNum += 1;
|
||||
Console.WriteLine("当前击杀了" + nowKillMonsterNum + "个怪物");
|
||||
}
|
||||
}
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("Hello, World!");
|
||||
#region 第一题
|
||||
Mother mother = new Mother();
|
||||
Father father = new Father();
|
||||
Son son = new Son();
|
||||
|
||||
mother.beginEat += father.Eating;
|
||||
mother.beginEat += son.Eating;
|
||||
mother.beginEat += mother.Eating;
|
||||
|
||||
mother.Cooking();
|
||||
Console.WriteLine("_______________________");
|
||||
#endregion
|
||||
|
||||
Monster m = new Monster();
|
||||
Player p = new Player();
|
||||
Panel panel = new Panel();
|
||||
Achievement achievement = new Achievement();
|
||||
|
||||
m.deadDoSomething += p.MonsterDeadDoSomething;
|
||||
m.deadDoSomething += panel.MonsterDeadDoSomething;
|
||||
m.deadDoSomething += achievement.MonsterDeadDoSomething;
|
||||
m.Dead();
|
||||
m.Dead();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -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,102 @@
|
||||
namespace Lesson13_事件
|
||||
{
|
||||
#region 知识点一 事件是什么
|
||||
//事件是基于委托的存在
|
||||
//事件是委托的安全包裹
|
||||
//让委托的使用具有安全性
|
||||
//事件 是一种特殊的变量类型
|
||||
#endregion
|
||||
|
||||
#region 知识点二 事件怎么使用
|
||||
//声明语法:
|
||||
//访问修饰符 event 委托类型 事件名称;
|
||||
//事件的使用:
|
||||
//1.事件是作为 成员变量存在于类中
|
||||
//2.委托怎么用 事件就怎么用
|
||||
|
||||
//事件相对于委托的区别
|
||||
//1.不能在类外部 赋值
|
||||
//2.不能在类外部 调用
|
||||
//注意:
|
||||
//他只能作为成员存在于类和接口以及结构体中
|
||||
class Test
|
||||
{
|
||||
//委托成员变量 用于存储 函数
|
||||
public Action myFun;
|
||||
//事件成员变量 用于存储 函数
|
||||
public event Action myEvent;
|
||||
|
||||
public Test()
|
||||
{
|
||||
//事件的使用和委托 一模一样 只是有些细微的区别
|
||||
myFun = TestFun;
|
||||
myFun += TestFun;
|
||||
myFun.Invoke();
|
||||
myFun();
|
||||
myFun = null;
|
||||
|
||||
myEvent = TestFun;
|
||||
myEvent += TestFun;
|
||||
myEvent.Invoke();
|
||||
myEvent();
|
||||
myEvent = null;
|
||||
}
|
||||
|
||||
|
||||
public void TestFun()
|
||||
{
|
||||
Console.WriteLine("TestFun");
|
||||
}
|
||||
|
||||
|
||||
public void DoEvent()
|
||||
{
|
||||
if (myEvent != null)
|
||||
{
|
||||
myEvent();
|
||||
}
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 知识点三 为什么有事件
|
||||
#endregion
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Test t = new Test();
|
||||
//委托可以在外部赋值
|
||||
t.myFun += TestFunOut;
|
||||
t.myFun = null;
|
||||
|
||||
//事件不能在外部赋值
|
||||
//但事件可以在外部添加函数
|
||||
//t.myEvent = null;//错误 事件不能在类外部赋值
|
||||
//t.myEvent = TestFunOut;//错误 事件不能在类外部赋值
|
||||
t.myEvent += TestFunOut;
|
||||
t.myEvent -= TestFunOut;//正确
|
||||
|
||||
|
||||
//事件不能在外部调用
|
||||
t.myFun();
|
||||
t.myFun.Invoke();
|
||||
//t.myEvent();//错误 事件不能在类外部调用
|
||||
//t.myEvent.Invoke();//错误 事件不能在类外部调用
|
||||
|
||||
//如果需要在外部调用,那么最好在类中提供一个调用事件的函数
|
||||
t.DoEvent();
|
||||
|
||||
|
||||
Action a = TestFunOut;
|
||||
//event Action a1 = TestFunOut;//
|
||||
|
||||
//总结
|
||||
//事件是对委托的安全包裹
|
||||
}
|
||||
static void TestFunOut()
|
||||
{
|
||||
Console.WriteLine("TestFunOut");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,52 @@
|
||||
namespace Lesson13_事件练习
|
||||
{
|
||||
class Heater
|
||||
{
|
||||
public event Action<int> Boiled;
|
||||
private int temperature = 25;
|
||||
public void AddHeat()
|
||||
{
|
||||
while (temperature != 100)
|
||||
{
|
||||
temperature += 1;
|
||||
Console.WriteLine("目前水温:" + temperature);
|
||||
Thread.Sleep(20);
|
||||
if(temperature >= 95)
|
||||
{
|
||||
if (Boiled != null)
|
||||
{
|
||||
Boiled(temperature);
|
||||
}
|
||||
Boiled = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
class Alarm
|
||||
{
|
||||
public void ShowInfo(int value)
|
||||
{
|
||||
Console.WriteLine("报警器:" + value + "度");
|
||||
}
|
||||
}
|
||||
class Displayer
|
||||
{
|
||||
public void Showinfo(int value)
|
||||
{
|
||||
Console.WriteLine("显示器:" + value + "度");
|
||||
}
|
||||
}
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Heater h = new Heater();
|
||||
Alarm a = new Alarm();
|
||||
Displayer d = new Displayer();
|
||||
h.Boiled += a.ShowInfo;
|
||||
h.Boiled += d.Showinfo;
|
||||
|
||||
h.AddHeat();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,124 @@
|
||||
namespace Lesson14_匿名函数
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
#region 知识点一 什么是匿名函数
|
||||
//顾名思义 就是没有名字的函数
|
||||
//匿名函数的使用主要是配合委托和事件进行使用
|
||||
//脱离委托和事件 是不会使用匿名函数的
|
||||
#endregion
|
||||
|
||||
#region 知识点二 基本语法
|
||||
//delegate (参数列表)
|
||||
//{
|
||||
// //函数体
|
||||
// return 返回值;
|
||||
//};
|
||||
//何时使用?
|
||||
//1.函数中传递委托参数时
|
||||
//2.委托或事件赋值时
|
||||
#endregion
|
||||
|
||||
#region 知识点三 使用
|
||||
//注意:无法直接在函数中定义匿名函数,必须使用委托变量来接收匿名函数
|
||||
//1.无参无返回
|
||||
Action a = delegate ()//用一个无参无返回的委托变量 来接收匿名函数
|
||||
{
|
||||
Console.WriteLine("无参无返回匿名函数逻辑");
|
||||
};
|
||||
a(); //调用匿名函数
|
||||
|
||||
|
||||
//2.有参
|
||||
Action<int, string> a2 = delegate (int a, string b)
|
||||
{
|
||||
Console.WriteLine($"有参无返回的匿名函数逻辑,参数a:{a},参数b:{b}");
|
||||
};
|
||||
a2(10, "hello");
|
||||
|
||||
|
||||
//3.有返回值
|
||||
Func<int> f = delegate ()
|
||||
{
|
||||
Console.WriteLine("无参有返回值的匿名函数逻辑");
|
||||
return 10;
|
||||
};
|
||||
Console.WriteLine(f());
|
||||
|
||||
|
||||
//4.一般情况会作为函数参数传递 或者 作为函数返回值
|
||||
Test t = new Test();
|
||||
|
||||
Action ac = delegate ()
|
||||
{
|
||||
Console.WriteLine("作为类成员变量的匿名函数逻辑");
|
||||
};
|
||||
|
||||
|
||||
|
||||
//参数传递
|
||||
t.Dosomething(100, delegate()
|
||||
{
|
||||
Console.WriteLine("作为参数传递的匿名函数逻辑");
|
||||
});
|
||||
t.Dosomething(200, ac);
|
||||
|
||||
|
||||
|
||||
|
||||
//返回值
|
||||
Action ac2 = t.GetFun();//可以先接收返回的匿名函数
|
||||
ac2();//调用函数
|
||||
|
||||
//也可以直接调用返回的匿名函数
|
||||
t.GetFun()();
|
||||
#endregion
|
||||
|
||||
#region 知识点四 匿名函数的缺点
|
||||
//添加到委托或事件中的匿名函数 无法被移除
|
||||
Action ac3 = delegate ()
|
||||
{
|
||||
Console.WriteLine("匿名函数1");
|
||||
};
|
||||
|
||||
ac3 += delegate ()
|
||||
{
|
||||
Console.WriteLine("匿名函数2");
|
||||
};
|
||||
ac3();//调用时 会依次调用两个匿名函数
|
||||
//因为匿名函数没有名字 所以无法通过名字来移除
|
||||
//ac3 -= ???
|
||||
//所以只能通过清空委托变量来移除
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
class Test
|
||||
{
|
||||
public Action action;
|
||||
|
||||
|
||||
//作为函数参数传递匿名函数
|
||||
public void Dosomething(int a,Action fun)
|
||||
{
|
||||
Console.WriteLine(a);
|
||||
fun();
|
||||
}
|
||||
|
||||
//作为函数返回值返回匿名函数
|
||||
public Action GetFun()
|
||||
{
|
||||
return delegate ()
|
||||
{
|
||||
Console.WriteLine("作为返回值 函数内部返回的函数逻辑");
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
// 总结
|
||||
// 匿名函数 就是没有名字的函数
|
||||
// 固定写法//delegate (参数列表){}
|
||||
// 主要是在 委托传递和存储时 为了方便可以直接使用倪敏该函数
|
||||
// 缺点是 没有办法指定移除
|
||||
}
|
||||
@@ -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,19 @@
|
||||
namespace Lesson14_匿名函数练习
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Func<int, int> func = Dosomething(3);
|
||||
int result = func(2);
|
||||
Console.WriteLine(result);
|
||||
}
|
||||
public static Func<int, int> Dosomething(int value)
|
||||
{
|
||||
return delegate (int x)
|
||||
{
|
||||
return value * x;
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,97 @@
|
||||
namespace Lesson15_lambda表达式
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
#region 知识点一 什么时lambda表达式
|
||||
//可以将lambda表达式理解为 匿名函数的简写
|
||||
//它除了写法不同外
|
||||
//使用上和匿名函数是一样的
|
||||
//都是配合委托类型使用的
|
||||
#endregion
|
||||
|
||||
#region 知识点二 lambda表达式的语法
|
||||
//匿名函数
|
||||
//delegate(参数列表){函数体};
|
||||
|
||||
//lambda表达式
|
||||
//(参数列表)=>{函数体};
|
||||
#endregion
|
||||
|
||||
#region 知识点三 使用
|
||||
//1.无参无返回值的lambda表达式
|
||||
Action a = () =>
|
||||
{
|
||||
Console.WriteLine("无参无返回的lambda表达式函数");
|
||||
};
|
||||
a();
|
||||
|
||||
//2.有参无返回值的lambda表达式
|
||||
Action<int> a2 = (int i1) =>
|
||||
{
|
||||
Console.WriteLine($"有参无返回的lambda表达式 参数i1:{i1}");
|
||||
};
|
||||
a2(100);
|
||||
|
||||
//3.有参的lambda表达式,甚至参数类型都可以省略 参数类型和委托或事件容器一致
|
||||
Action<int> a3 = (i1) =>
|
||||
{
|
||||
Console.WriteLine($"有参无返回的lambda表达式 参数i1:{i1}");
|
||||
};
|
||||
a3(200);
|
||||
|
||||
//4.有返回值的lambda表达式
|
||||
Func<int, int, int> f = (i1, i2) =>
|
||||
{
|
||||
Console.WriteLine($"有返回的lambda,将返回{i1}与{i2}相加");
|
||||
return i1 + i2;
|
||||
};
|
||||
Console.WriteLine(f(10, 20));
|
||||
#endregion
|
||||
|
||||
Test t = new Test();
|
||||
t.Dosomething();
|
||||
}
|
||||
}
|
||||
#region 知识点四 闭包
|
||||
//内层的函数可以引用包含在它外层的变量
|
||||
//即使外层函数已经执行完毕
|
||||
//注意:
|
||||
//该变量提供的值并不是变量创建时的值,而是在父函数范围内最后一次被修改的值
|
||||
#endregion
|
||||
|
||||
class Test
|
||||
{
|
||||
public event Action action;
|
||||
public Test()
|
||||
{
|
||||
int value = 10;
|
||||
//这里就是一个闭包的例子
|
||||
//因为 当构造函数执行完毕后 value变量的生命周期应该结束了
|
||||
//但是由于action引用了value变量
|
||||
//所以value变量的生命周期被延长了
|
||||
action = () =>
|
||||
{
|
||||
Console.WriteLine($"闭包value的值为:{value}");
|
||||
};
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
int index = i;//解决闭包问题的常用方法
|
||||
//每次都是新创建的index变量,所以可以保存当时的值
|
||||
//但是i是在循环里的,所以每次循环都是同一个i变量,所以最终闭包引用的i变量的值就是循环结束时的值10
|
||||
action += () =>
|
||||
{
|
||||
Console.WriteLine($"闭包循环i的值为:{i}");
|
||||
Console.WriteLine($"闭包循环index的值为:{index}");
|
||||
};
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
public void Dosomething()
|
||||
{
|
||||
action();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,50 @@
|
||||
namespace Lesson15_lambda表达式练习
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
a1()();
|
||||
a2()();
|
||||
}
|
||||
|
||||
public static Action a1()
|
||||
{
|
||||
Action action = null;
|
||||
for (int i = 1; i <= 10; i++)
|
||||
{
|
||||
int index = i;
|
||||
action += delegate()
|
||||
{
|
||||
Console.WriteLine(index);
|
||||
};
|
||||
}
|
||||
return action;
|
||||
}
|
||||
public static Action a2()
|
||||
{
|
||||
Action action = null;
|
||||
for (int i = 1; i <= 10; i++)
|
||||
{
|
||||
int index = i;
|
||||
action += () => Show(index);
|
||||
}
|
||||
return action;
|
||||
}
|
||||
public static Action a3()
|
||||
{
|
||||
Action action = null;
|
||||
for (int i = 1; i <= 10; i++)
|
||||
{
|
||||
int index = i;
|
||||
action += () => Show(index);
|
||||
}
|
||||
return action;
|
||||
}
|
||||
static void Show(int x)
|
||||
{
|
||||
Console.WriteLine(x);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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,146 @@
|
||||
using System.Collections.Generic;
|
||||
namespace Lesson16_List排序
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
#region 知识点一 List自带的排序方法
|
||||
List<int> list = new List<int>();
|
||||
list.Add(3);
|
||||
list.Add(2);
|
||||
list.Add(4);
|
||||
list.Add(6);
|
||||
list.Add(5);
|
||||
list.Add(1);
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
Console.WriteLine(list[i]);
|
||||
}
|
||||
Console.WriteLine("_________________________");
|
||||
//list提供了sort方法,可以对list进行排序,默认是升序排序
|
||||
list.Sort();
|
||||
for (int i = 0; i < list.Count; i++)
|
||||
{
|
||||
Console.WriteLine(list[i]);
|
||||
}
|
||||
//Arraylist中也有sort方法
|
||||
#endregion
|
||||
|
||||
#region 知识点二 自定义类的排序
|
||||
Console.WriteLine("_________________________");
|
||||
List<Item> itemList = new List<Item>();
|
||||
itemList.Add(new Item(45));
|
||||
itemList.Add(new Item(10));
|
||||
itemList.Add(new Item(99));
|
||||
itemList.Add(new Item(24));
|
||||
itemList.Add(new Item(100));
|
||||
itemList.Add(new Item(12));
|
||||
itemList.Sort();//无法排序,自定义类没有默认的排序规则,不知道按哪个字段排序
|
||||
for (int i = 0; i < itemList.Count; i++)
|
||||
{
|
||||
Console.WriteLine(itemList[i].money);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 知识点三 通过委托函数进行排序
|
||||
List<ShopItem> shopItems = new List<ShopItem>();
|
||||
shopItems.Add(new ShopItem(5));
|
||||
shopItems.Add(new ShopItem(2));
|
||||
shopItems.Add(new ShopItem(3));
|
||||
shopItems.Add(new ShopItem(6));
|
||||
shopItems.Add(new ShopItem(4));
|
||||
shopItems.Add(new ShopItem(1));
|
||||
|
||||
//通过委托函数进行排序
|
||||
//shopItems.Sort(SortShopItem);
|
||||
|
||||
//通过匿名函数表达式进行排序
|
||||
//shopItems.Sort(delegate(ShopItem a,ShopItem b) {
|
||||
// if (a.price > b.price)
|
||||
// {
|
||||
// return 1;
|
||||
// }
|
||||
// else if (a.price == b.price)
|
||||
// {
|
||||
// return 0;
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// return -1;
|
||||
// }
|
||||
//});
|
||||
|
||||
//通过lambda表达式结合三木运算符进行排序
|
||||
shopItems.Sort((a, b) => {
|
||||
return a.price > b.price ? 1 : -1;
|
||||
});
|
||||
|
||||
Console.WriteLine("_________________________");
|
||||
for (int i = 0; i < shopItems.Count; i++)
|
||||
{
|
||||
Console.WriteLine(shopItems[i].price);
|
||||
}
|
||||
#endregion
|
||||
}
|
||||
static int SortShopItem(ShopItem a,ShopItem b)
|
||||
{
|
||||
if (a.price > b.price)
|
||||
{
|
||||
return 1;
|
||||
}else if (a.price == b.price)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
class Item : IComparable<Item>
|
||||
{
|
||||
public int money;
|
||||
public Item(int money)
|
||||
{
|
||||
this.money = money;
|
||||
}
|
||||
|
||||
public int CompareTo(Item other)
|
||||
{
|
||||
//返回值的含义:
|
||||
//小于0:
|
||||
//相当于放在当前对象前面
|
||||
//等于0:
|
||||
//保持当前的位置不变
|
||||
//大于0:
|
||||
//相当于放在当前对象后面
|
||||
|
||||
|
||||
if ( this.money > other.money)
|
||||
{
|
||||
return 1;
|
||||
}else if (this.money == other.money)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
}
|
||||
class ShopItem
|
||||
{
|
||||
public int price;
|
||||
public ShopItem(int price)
|
||||
{
|
||||
this.price = price;
|
||||
}
|
||||
}
|
||||
}
|
||||
//总结:
|
||||
//系统自带的变量(int, float, double......) 一般都可以直接 Sort
|
||||
// 自定义类 Sort 有两种方式
|
||||
// 1. 继承接口 IComparable
|
||||
// 2. 在 Sort 中传入委托函数
|
||||
@@ -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,157 @@
|
||||
namespace Lesson16_List排序练习
|
||||
{
|
||||
class Monster
|
||||
{
|
||||
public int atk;
|
||||
public int def;
|
||||
public int hp;
|
||||
public Monster(int atk, int def, int hp)
|
||||
{
|
||||
this.atk = atk;
|
||||
this.def = def;
|
||||
this.hp = hp;
|
||||
}
|
||||
|
||||
override public string ToString()
|
||||
{
|
||||
return $"怪物:atk={atk},def={def},hp={hp}";
|
||||
}
|
||||
}
|
||||
enum E_Quality
|
||||
{
|
||||
白色 = 0,
|
||||
绿色 = 1,
|
||||
蓝色 = 2,
|
||||
紫色 = 3,
|
||||
橘色 = 4
|
||||
}
|
||||
enum E_ItemType
|
||||
{
|
||||
武器 = 0,
|
||||
护甲 = 1,
|
||||
饰品 = 2
|
||||
}
|
||||
class Item
|
||||
{
|
||||
public string name;
|
||||
public E_Quality quality;
|
||||
public E_ItemType itemType;
|
||||
|
||||
public Item(string name, E_Quality quality, E_ItemType itemType)
|
||||
{
|
||||
this.name = name;
|
||||
this.quality = quality;
|
||||
this.itemType = itemType;
|
||||
}
|
||||
|
||||
public override string ToString()
|
||||
{
|
||||
return $"物品:品质={quality},类型={itemType},名字={name}";
|
||||
}
|
||||
}
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
List<Monster> monsters = new List<Monster>();
|
||||
Random r = new Random();
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
monsters.Add(new Monster(r.Next(1, 10), r.Next(1, 10), r.Next(1, 10)));
|
||||
Console.WriteLine(monsters[i]);
|
||||
}
|
||||
Console.WriteLine("_______________________________");
|
||||
try
|
||||
{
|
||||
int inputIndex = int.Parse(Console.ReadLine());
|
||||
switch (inputIndex)
|
||||
{
|
||||
case 1:
|
||||
monsters.Sort((m1, m2) => m1.atk - m2.atk);
|
||||
break;
|
||||
case 2:
|
||||
monsters.Sort((m1, m2) => m1.def - m2.def);
|
||||
break;
|
||||
case 3:
|
||||
monsters.Sort((m1, m2) => m1.hp - m2.hp);
|
||||
break;
|
||||
case 4:
|
||||
//反转API
|
||||
monsters.Reverse();
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
Console.WriteLine("ERROR");
|
||||
}
|
||||
for (int i = 0; i < 10; i++)
|
||||
{
|
||||
Console.WriteLine(monsters[i]);
|
||||
}
|
||||
Console.WriteLine("_______________________________");
|
||||
|
||||
List<Item> items = new List<Item>();
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
E_Quality randomQuality = (E_Quality)r.Next(0, Enum.GetValues(typeof(E_Quality)).Length);
|
||||
E_ItemType randomItemType = (E_ItemType)r.Next(0, Enum.GetValues(typeof(E_ItemType)).Length);
|
||||
|
||||
items.Add(new Item("Item" + r.Next(100, 201), randomQuality, randomItemType));
|
||||
Console.WriteLine(items[i]);
|
||||
}
|
||||
Console.WriteLine("_______________________________");
|
||||
items.Sort((i1, i2) => {
|
||||
//先按类型比
|
||||
if (i1.itemType != i2.itemType)
|
||||
{
|
||||
return i1.itemType - i2.itemType;
|
||||
}
|
||||
//再按品质比
|
||||
else if (i1.quality != i2.quality)
|
||||
{
|
||||
return i2.quality - i1.quality;
|
||||
}
|
||||
else
|
||||
{
|
||||
return i1.name.CompareTo(i2.name);
|
||||
}
|
||||
});
|
||||
for (int i = 0; i < 100; i++)
|
||||
{
|
||||
Console.WriteLine(items[i]);
|
||||
}
|
||||
Console.WriteLine("_______________________________");
|
||||
|
||||
Dictionary<int, string> dic = new Dictionary<int, string>();
|
||||
dic.Add(1, "532132");
|
||||
dic.Add(3, "532132");
|
||||
dic.Add(4, "532132");
|
||||
dic.Add(2, "532132");
|
||||
dic.Add(6, "532132");
|
||||
dic.Add(5, "532132");
|
||||
|
||||
foreach (var kv in dic)
|
||||
{
|
||||
Console.WriteLine($"Key={kv.Key},Value={kv.Value}");
|
||||
}
|
||||
Console.WriteLine("_______________________________");
|
||||
List<KeyValuePair<int, string>> list = new List<KeyValuePair<int, string>>();
|
||||
|
||||
foreach (KeyValuePair<int,string> item in dic)
|
||||
{
|
||||
list.Add(item);
|
||||
}
|
||||
|
||||
list.Sort((p1, p2) =>
|
||||
{
|
||||
return p1.Key - p2.Key;
|
||||
});
|
||||
|
||||
for(int i = 0;i < list.Count;i++)
|
||||
{
|
||||
Console.WriteLine(list[i].Key + " " + list[i].Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,125 @@
|
||||
namespace Lesson18_多线程
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static bool isRunning = true;
|
||||
static object obj = new object();
|
||||
static void Main(string[] args)
|
||||
{
|
||||
#region 知识点一 了解线程前先了解进程
|
||||
// 进程(Process)是计算机中的程序关于某数据集合上的一次运行活动
|
||||
// 是系统进行资源分配和调度的基本单位,是操作系统结构的基础
|
||||
// 说人话:打开一个应用程序就是在操作系统上开启了一个进程
|
||||
// 进程之间可以相互独立运行,互不干扰
|
||||
// 进程之间也可以相互访问、操作
|
||||
#endregion
|
||||
|
||||
#region 知识点二 什么是线程
|
||||
// 操作系统能够进行运算调度的最小单位。
|
||||
// 它被包含在进程之中,是进程中的实际运作单位
|
||||
// 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程
|
||||
// 我们目前写的程序 都在主线程中
|
||||
|
||||
// 简单理解线程:
|
||||
// 就是代码从上到下运行的一条 “管道”
|
||||
#endregion
|
||||
|
||||
#region 知识点三 什么是多线程
|
||||
//我们可以通过代码 开启新的线程
|
||||
//可以同时运行代码的多条“管道”
|
||||
#endregion
|
||||
|
||||
#region 知识点四 语法相关
|
||||
//线程类 Thread
|
||||
//命名空间 System.Threading
|
||||
//1.声明一个新的线程
|
||||
// 注意 线程执行的代码 需要封装到一个函数中
|
||||
// 新线程 将要执行的代码逻辑 被封装到了一个函数语句中
|
||||
Thread t = new Thread(NewThreadLogic);
|
||||
|
||||
//2.启动线程
|
||||
//默认为前台线程,不受主线程影响,会一直运行
|
||||
t.Start();
|
||||
|
||||
//3.设置为后台线程
|
||||
//后台线程 会随着主线程的结束而结束
|
||||
t.IsBackground = true;
|
||||
|
||||
//4.关闭释放一个线程
|
||||
//如果开启的线程不是死循环,是能够结束的,那么不用刻意去关闭,它会自动释放
|
||||
//如果是死循环线程,那么有两种方式可以关闭
|
||||
//4.1-死循环中设置一个开关变量 来控制循环结束
|
||||
|
||||
//Console.ReadKey();//卡一下t线程,让其保持运行
|
||||
//isRunning = false;//按下后结束t线程
|
||||
|
||||
Console.ReadKey();//卡一下主线程,按下后结束
|
||||
|
||||
////4.2-通过线程提供的方法(注意在.NET Core及以后的版本中 不推荐使用该方法)
|
||||
////终止线程 不推荐使用该方法 可能会引发不可预知的问题
|
||||
//try
|
||||
//{
|
||||
// t.Abort();
|
||||
// t = null;
|
||||
//}
|
||||
//catch
|
||||
//{
|
||||
// Console.WriteLine("ERROR");
|
||||
//}
|
||||
//t = null;
|
||||
|
||||
//5.线程休眠
|
||||
//Thread.Sleep(1000);//让线程休眠一定时间,单位是毫秒
|
||||
//现在在主线程中休眠1秒钟
|
||||
|
||||
|
||||
#endregion
|
||||
|
||||
#region 知识点五 线程之间共享数据
|
||||
//多个线程使用的内存时共享的,都属于该应用程序的内存空间
|
||||
//所以要注意 当多线程 同时操作同一片内存区域时 可能会引发数据冲突问题
|
||||
//可以通过加锁的形式避免问题
|
||||
|
||||
//lock
|
||||
//当我们在做个线程中想要访问同样的类型数据时,可以使用lock关键字来锁定该数据
|
||||
//这样当一个线程在访问该数据时,其他线程就无法访问该数据,直到该线程访问完毕,释放锁
|
||||
//lock(引用类型的对象)
|
||||
|
||||
|
||||
while (true)
|
||||
{
|
||||
lock(obj)
|
||||
{
|
||||
Console.SetCursorPosition(0, 0);
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.Write("????????????");
|
||||
}
|
||||
}
|
||||
//注意:锁定的对象不能是值类型,必须是引用类型
|
||||
//而且锁也会影响性能,所以只锁定必要的代码段
|
||||
|
||||
#endregion
|
||||
|
||||
#region 知识点六 多线程对于我们的意义
|
||||
//可以用多线程专门处理一些复杂耗时的逻辑
|
||||
//比如 寻路、网络通信等等
|
||||
#endregion
|
||||
}
|
||||
|
||||
static void NewThreadLogic()
|
||||
{
|
||||
|
||||
while (isRunning)
|
||||
{
|
||||
//Thread.Sleep(1000);
|
||||
//Console.WriteLine("NewThreadLogic");
|
||||
lock (obj)
|
||||
{
|
||||
Console.SetCursorPosition(10, 5);
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine("※");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,113 @@
|
||||
namespace Lesson18_多线程练习
|
||||
{
|
||||
enum E_Direction
|
||||
{
|
||||
Up,
|
||||
Down,
|
||||
Left,
|
||||
Right
|
||||
}
|
||||
struct Position
|
||||
{
|
||||
public int X;
|
||||
public int Y;
|
||||
}
|
||||
interface IDraw
|
||||
{
|
||||
public void Draw();
|
||||
}
|
||||
class Snake : IDraw
|
||||
{
|
||||
public E_Direction Direction;
|
||||
Position Position;
|
||||
public Snake()
|
||||
{
|
||||
Position.X = 15;
|
||||
Position.Y = 5;
|
||||
Direction = E_Direction.Right;
|
||||
}
|
||||
public Snake(int x, int y,E_Direction direction)
|
||||
{
|
||||
Position.X = x;
|
||||
Position.Y = y;
|
||||
Direction = direction;
|
||||
}
|
||||
|
||||
public void Move()
|
||||
{
|
||||
switch (this.Direction)
|
||||
{
|
||||
case E_Direction.Up:
|
||||
Position.Y -= 1;
|
||||
break;
|
||||
case E_Direction.Down:
|
||||
Position.Y += 1;
|
||||
break;
|
||||
case E_Direction.Left:
|
||||
Position.X -= 2;
|
||||
break;
|
||||
case E_Direction.Right:
|
||||
Position.X += 2;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
public void Draw()
|
||||
{
|
||||
Console.SetCursorPosition(Position.X, Position.Y);
|
||||
Console.Write("■");
|
||||
}
|
||||
public void Clean()
|
||||
{
|
||||
Console.SetCursorPosition(Position.X, Position.Y);
|
||||
Console.Write(" ");
|
||||
}
|
||||
public void ChangeDirection(E_Direction direction)
|
||||
{
|
||||
this.Direction = direction;
|
||||
}
|
||||
}
|
||||
class Program
|
||||
{
|
||||
static Snake snake;
|
||||
static void Main(string[] args)
|
||||
{
|
||||
snake = new Snake();
|
||||
Console.CursorVisible = false;
|
||||
Thread inputThread = new Thread(input);
|
||||
inputThread.Start();
|
||||
while (true)
|
||||
{
|
||||
Thread.Sleep(500);
|
||||
snake.Clean();
|
||||
snake.Move();
|
||||
snake.Draw();
|
||||
}
|
||||
|
||||
}
|
||||
static void input()
|
||||
{
|
||||
while (true)
|
||||
{
|
||||
switch(Console.ReadKey(true).Key)
|
||||
{
|
||||
case ConsoleKey.UpArrow:
|
||||
snake.ChangeDirection(E_Direction.Up);
|
||||
break;
|
||||
case ConsoleKey.DownArrow:
|
||||
snake.ChangeDirection(E_Direction.Down);
|
||||
break;
|
||||
case ConsoleKey.LeftArrow:
|
||||
snake.ChangeDirection(E_Direction.Left);
|
||||
break;
|
||||
case ConsoleKey.RightArrow:
|
||||
snake.ChangeDirection(E_Direction.Right);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,73 @@
|
||||
#define Unity5
|
||||
#define Unity2019
|
||||
#undef Unity2019//下面#if判断Unity2019会失效
|
||||
|
||||
|
||||
|
||||
using System;
|
||||
namespace Lesson19_预处理器指令
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
#region 知识点一 什么是编译器
|
||||
//编译器是一种翻译程序
|
||||
//他用将元语言程序翻译为目标语言程序
|
||||
|
||||
//源语言程序:某种程序设计语言写成的,比如C#、Java、C++等语言写的程序
|
||||
//目标语言程序:二进制数表示的为机器代码写成的程序
|
||||
#endregion
|
||||
|
||||
#region 知识点二 什么是预处理器指令
|
||||
//预处理器指令 知道编译器 在实际编译源代码之前 对信息进行预处理
|
||||
//预处理器指令 都是以 # 开头的指令
|
||||
//预处理器指令不是语句,所以他们不以;分号结束
|
||||
//目前我们经常用到的 折叠代码块 就是预处理器指令
|
||||
#endregion
|
||||
|
||||
#region 知识点三 常见的预处理器指令
|
||||
//1
|
||||
//#define
|
||||
//定义一个符号,类似一个没有值的常量
|
||||
//#undef
|
||||
//取消define定义的符号,让其失效
|
||||
//两者都是写在脚本文件最前面
|
||||
//一般配合if指令使用 或配合特性
|
||||
|
||||
//2
|
||||
//#if
|
||||
//#elif
|
||||
//#else
|
||||
//#endif
|
||||
//和if语句规则一样,一般配合#define指令使用
|
||||
//用于告诉编译器惊醒编译代码流程控制
|
||||
|
||||
|
||||
//如果发现有Unity4这个符号那么其中包含的代码就会被编译器翻译
|
||||
//可以通过逻辑或和逻辑与进行多种符号的组合判断
|
||||
#if Unity4 && !Unity2019
|
||||
Console.WriteLine("使用版本Unity4编译代码");
|
||||
#elif Unity2019 //undef了Unity2019 所以这里的判断是false
|
||||
Console.WriteLine("使用版本Unity2019编译代码");
|
||||
#elif Unity5
|
||||
#warning 这个版本不合法 //发出警告信息
|
||||
Console.WriteLine("使用版本Unity5编译代码");
|
||||
#error 版本过旧请升级 //发出错误信息
|
||||
#endif
|
||||
|
||||
//3
|
||||
//#warning
|
||||
//#error
|
||||
//告诉编译器
|
||||
//是发出警告信息 还是错误信息
|
||||
//编译器会在编译时显示这些信息
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
//总结
|
||||
//预处理器指令
|
||||
//可以让代码还没有编译之前就可以进行一些预处理判断
|
||||
//在Unity中国会用来惊醒一些平台或者版本的判断
|
||||
//决定不同的版本或不同平台使用不同的代码逻辑
|
||||
@@ -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,34 @@
|
||||
|
||||
|
||||
#define Unity2017
|
||||
#define Unity2020
|
||||
|
||||
|
||||
namespace Lesson19_预处理器指令练习
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Console.WriteLine("请输入第一个数字:");
|
||||
int a = int.Parse(Console.ReadLine());
|
||||
|
||||
Console.WriteLine("请输入第二个数字:");
|
||||
int b = int.Parse(Console.ReadLine());
|
||||
Console.WriteLine(Calc(a, b));
|
||||
|
||||
}
|
||||
static int Calc(int a, int b)
|
||||
{
|
||||
#if Unity5
|
||||
return a + b;
|
||||
#elif Unity2017
|
||||
return a*b;
|
||||
#elif Unity2019
|
||||
return a-b;
|
||||
#else
|
||||
return 0;
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,321 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace Lesson20_反射
|
||||
{
|
||||
#region 知识回顾
|
||||
//编译器是一种翻译程序
|
||||
//它用于将源语言程序翻译为目标语言程序
|
||||
|
||||
//源语言程序:某种程序设计语言写成的,比如C#、Java、Python等
|
||||
//目标语言程序:计算机能够直接执行的机器语言程序(伪代码)
|
||||
#endregion
|
||||
|
||||
#region 知识点一 什么是程序集
|
||||
//程序集是我们写的一个代码集合,我们现在写的所有代码
|
||||
//最终都会背编译成一个程序集文件供别人使用
|
||||
//程序集文件的扩展名有两种:.exe和.dll
|
||||
//.exe:可执行程序文件,双击即可运行
|
||||
//.dll:类库文件,不能直接运行,需要被其他程序调用才能运行
|
||||
#endregion
|
||||
|
||||
#region 知识点二 元数据
|
||||
//元数据就是用来描述数据的数据
|
||||
//这个概念不仅仅用于程序上,在别的领域也有元数据
|
||||
|
||||
//说人话:
|
||||
//程序中的类,类中的函数、变量等等信息就是 程序的 元数据
|
||||
//有关程序以及类型的数据被称为 元数据,他们保存在程序集文件中
|
||||
#endregion
|
||||
|
||||
#region 知识点三 反射的概念
|
||||
//程序在运行时,可以查看其他程序集或者自身的元数据
|
||||
//一个运行的程序查看本身或者其他程序集的元数据的过程 就叫做 反射
|
||||
|
||||
//说人话:
|
||||
//在程序运行时,通过反射可以得到其他程序集或者自己程序集代码的各种信息
|
||||
//类,函数,变量,对象等等,实例化他们,执行他们,操作他们
|
||||
#endregion
|
||||
|
||||
#region 知识点四 反射的作用
|
||||
//因为反射可以在程序变异后获得信息,所以他提高了程序的拓展性和灵活性
|
||||
//1.程序运行时得到所有元数据,包括元数据的特性
|
||||
//2.程序运行时,实例化对象,操作对象
|
||||
//3.程序运行时创建新对象,用这些对象执执行任务
|
||||
#endregion
|
||||
|
||||
|
||||
class Test
|
||||
{
|
||||
private int i = 1;
|
||||
public int j = 2;
|
||||
public string str = "123";
|
||||
|
||||
public Test()
|
||||
{
|
||||
|
||||
}
|
||||
public Test(int i)
|
||||
{
|
||||
this.i = i;
|
||||
|
||||
}
|
||||
public Test(int i ,string str)
|
||||
{
|
||||
this.i = i;
|
||||
this.str = str;
|
||||
}
|
||||
}
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
|
||||
#region 知识点五 语法相关
|
||||
|
||||
#region Type类
|
||||
//Type(类的信息类)
|
||||
//他是反射功能的基础!
|
||||
//他是访问元数据的主要方式
|
||||
//使用Type的成员获取有关类型的声明信息
|
||||
//有关类型的成员(如构造函数、方法、属性、字段、事件等)
|
||||
|
||||
#region 获取Type对象的方式
|
||||
//1.万物之父 Object类的GetType()方法
|
||||
int a = 42;
|
||||
Type type = a.GetType();//得到int类型的类的信息
|
||||
Console.WriteLine(type);//获取int命名空间的全名 System.Int32
|
||||
//2.通过typeof关键字获取
|
||||
Type type2 = typeof(string);//得到string类型的类的信息
|
||||
Console.WriteLine(type2);//获取string命名空间的全名 System.String
|
||||
//3.通过类的名字 也可以获取类型
|
||||
// 注意 类名必须包含命名空间 不然找不到
|
||||
Type type3 = Type.GetType("Int32");//非全名
|
||||
Console.WriteLine(type3);//获取不到 输出空行
|
||||
type3 = Type.GetType("System.Int32");//全名
|
||||
Console.WriteLine(type3);//获取int命名空间的全名 System.Int32
|
||||
Console.WriteLine("__________________________");
|
||||
#endregion
|
||||
|
||||
#region 得到类的程序集信息
|
||||
//可以通过Type得到类型所在的程序集信息
|
||||
Console.WriteLine(type.Assembly);
|
||||
Console.WriteLine(type2.Assembly);
|
||||
Console.WriteLine(type3.Assembly);
|
||||
Console.WriteLine("__________________________");
|
||||
#endregion
|
||||
|
||||
#region 获取类中的所有公共成员
|
||||
//首先得到Type
|
||||
Type t = typeof(Test);
|
||||
//然后得到所有公共成员
|
||||
//需要引用命名空间 using System.Reflection;
|
||||
MemberInfo[] infos = t.GetMembers();
|
||||
for (int i = 0; i < infos.Length; i++)
|
||||
{
|
||||
Console.WriteLine(infos[i]);
|
||||
}
|
||||
Console.WriteLine("__________________________");
|
||||
#endregion
|
||||
|
||||
#region 获取类的公共构造函数并调用
|
||||
//1.获取所有构造函数
|
||||
ConstructorInfo[] ctors = t.GetConstructors();
|
||||
for (int i = 0; i < ctors.Length; i++)
|
||||
{
|
||||
Console.WriteLine(ctors[i]);
|
||||
}
|
||||
Console.WriteLine("__________________________");
|
||||
|
||||
|
||||
|
||||
//2.获取其中一个构造函数并执行
|
||||
//得到构造函数传入 Type数组 数组中内容按顺序时参数类型
|
||||
//执行构造函数传入 Object数组 表示按顺序传入的参数值
|
||||
|
||||
// 2-1得到无参构造并执行
|
||||
ConstructorInfo info = t.GetConstructor(new Type[0]);//由于使用时必须要传入参数类型数组 所以无参时传入空数组
|
||||
//执行无参构造方法
|
||||
//info.Invoke(null);//因为是无参构造函数,所以传入参数为null
|
||||
//甚至可以实例化
|
||||
Test obj = info.Invoke(null) as Test;
|
||||
Console.WriteLine(obj.j);
|
||||
Console.WriteLine("__________________________");
|
||||
// 2-2得到无参构造并执行
|
||||
ConstructorInfo info2 = t.GetConstructor(new Type[] { typeof(int)});
|
||||
//执行有参构造方法
|
||||
Test obj2 = info2.Invoke(new object[] { 10 }) as Test;
|
||||
//Console.WriteLine(obj2.i);//i是private类型所以外部无法访问
|
||||
//执行两个参数的构造函数
|
||||
ConstructorInfo info3 = t.GetConstructor(new Type[] { typeof(int), typeof(string) });
|
||||
Test obj3 = info3.Invoke(new object[] { 6 , "123" }) as Test;
|
||||
Console.WriteLine(obj.str);
|
||||
Console.WriteLine("__________________________");
|
||||
#endregion
|
||||
|
||||
#region 获取类的公共成员变量
|
||||
//1.得到所有成员变量名和类型
|
||||
FieldInfo[] fieldInfos = t.GetFields();
|
||||
for (int i = 0; i < fieldInfos.Length; i++)
|
||||
{
|
||||
Console.WriteLine(fieldInfos[i]);
|
||||
}
|
||||
Console.WriteLine("__________________________");
|
||||
//2.得到指定成员变量名和类型
|
||||
FieldInfo infoJ = t.GetField("j");
|
||||
Console.WriteLine(infoJ);
|
||||
Console.WriteLine("__________________________");
|
||||
//3.通过反射获取和设置成员变量的值
|
||||
Test test = new Test();
|
||||
test.j = 99;
|
||||
test.str = "2222";
|
||||
//3-1获取成员变量j的值
|
||||
Console.WriteLine(infoJ.GetValue(test));//注意这里需要传入对象,因为都是写在一个文档里所以直接写上面new的test了
|
||||
//如果是其他程序集中则需要先通过反射实例化对象再传入
|
||||
//3-2设置成员变量j的值
|
||||
infoJ.SetValue(test, 100);
|
||||
Console.WriteLine(infoJ.GetValue(test));
|
||||
Console.WriteLine("__________________________");
|
||||
#endregion
|
||||
|
||||
#region 获取类的公共成员方法
|
||||
//通过Type类中的 GetMethods()方法可以获取类的所有公共方法
|
||||
//MethodInfo是方法的反射信息类
|
||||
Type strType = typeof(string);
|
||||
//1.如果存在方法重载 用Type数组表示参数类型
|
||||
MethodInfo[] methods = strType.GetMethods();
|
||||
for (int i = 0; i < methods.Length; i++)
|
||||
{
|
||||
Console.WriteLine(methods[i]);
|
||||
}
|
||||
Console.WriteLine("__________________________");
|
||||
//2.调用该方法
|
||||
//注意:如果是静态方法 则传入null 如果是实例方法 则传入对象
|
||||
MethodInfo subStr = strType.GetMethod("Substring",new Type[] { typeof(int),typeof(int)});
|
||||
string str = "hello world!";
|
||||
object result = subStr.Invoke(str, new Object[] { 7, 5 });
|
||||
Console.WriteLine(result);
|
||||
Console.WriteLine("__________________________");
|
||||
#endregion
|
||||
|
||||
#region 其他
|
||||
//Type;
|
||||
//得枚举
|
||||
//GetEnumName();
|
||||
//GetEnumNames();
|
||||
|
||||
//得事件
|
||||
//GetEvent();
|
||||
//GetEvents();
|
||||
|
||||
//得接口
|
||||
//GetInterface();
|
||||
//GetInterfaces();
|
||||
|
||||
//得属性
|
||||
//GetProperty();
|
||||
//GetPropertys();
|
||||
|
||||
//还有很多其他方法 可以查看文档学习
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
#region Assembly类
|
||||
//程序集类
|
||||
//主要用来加载其他程序集,加载后
|
||||
//才能用Type来使用其他程序集中的信息
|
||||
//如果想要使用不是自己程序集中的内容 需要先加载程序集
|
||||
//比如dll文件(库文件)
|
||||
//简单的把库文件看成一种代码仓库,它提供给使用者一些可以直接拿来用的变量、函数、类等等
|
||||
|
||||
//三种加载程序集的函数
|
||||
//一般用来加载在同一文件下的其他程序集
|
||||
//Assembly asembly2= Assembly.Load("程序集名称");
|
||||
|
||||
//一般用来加载不在同一文件下的其它程序集
|
||||
//Assembly asembly = Assembly.LoadFrom("包含程序集清单的文件的名称或路径");
|
||||
//Assembly asembly3 = Assembly.LoadFile("要加载的文件的完全限定路径");
|
||||
|
||||
//1.先加载一个指定程序集
|
||||
Assembly asembly = Assembly.LoadFrom(@"D:\VisualStudio2022\VisualStudio Programe\C#\C#进阶\Lesson18_多线程练习\bin\Debug\net8.0\Lesson18_多线程练习.dll");
|
||||
|
||||
#region 如果不知道程序集载入的对不对可以用这个方法看一下
|
||||
Type[] types = asembly.GetTypes();
|
||||
foreach (Type item in types)
|
||||
{
|
||||
Console.WriteLine(item.FullName);
|
||||
}
|
||||
#endregion
|
||||
|
||||
//2.再加载程序集中的一个类对象 之后才能使用反射
|
||||
Type snake = asembly.GetType("Lesson18_多线程练习.Snake");
|
||||
|
||||
#region 如果不知道有什么成员可以用这个方法看一下
|
||||
MemberInfo[] members = snake.GetMembers();
|
||||
for (int i = 0; i < members.Length; i++)
|
||||
{
|
||||
Console.WriteLine(members[i]);
|
||||
}
|
||||
#endregion
|
||||
|
||||
//通过反射 实例化一个 Snake对象
|
||||
//先把枚举也传过来,来得到可传入的参数
|
||||
Type moveDir = asembly.GetType("Lesson18_多线程练习.E_Direction");
|
||||
FieldInfo right = moveDir.GetField("Right");
|
||||
//再实例化Snake对象
|
||||
Object snakeObj = Activator.CreateInstance(snake, 10 ,5 , right.GetValue(null));
|
||||
|
||||
//通过反射调用Snake对象的方法
|
||||
MethodInfo move = snake.GetMethod("Move");
|
||||
MethodInfo draw = snake.GetMethod("Draw");
|
||||
MethodInfo clean = snake.GetMethod("Clean");
|
||||
Console.Clear();
|
||||
while (true)
|
||||
{
|
||||
Thread.Sleep(400);
|
||||
clean.Invoke(snakeObj, null);
|
||||
move.Invoke(snakeObj, null);
|
||||
draw.Invoke(snakeObj, null);
|
||||
}
|
||||
|
||||
//3.类库工程的创建
|
||||
//在Visual Studio中新建一个项目 选择 类库工程
|
||||
#endregion
|
||||
|
||||
#region Activator类
|
||||
//用于快速实例化对象的类
|
||||
//用于将Type对象快速转换为实例对象
|
||||
//先得到Type 然后快速实例化对象
|
||||
Type testType = typeof(Test);
|
||||
//1.无参构造
|
||||
Test testObj = Activator.CreateInstance(testType) as Test;
|
||||
Console.WriteLine(testObj.str);
|
||||
//2.有参构造
|
||||
Test testObj2 = Activator.CreateInstance(testType, 99) as Test;//一个参数的有参构造函数
|
||||
Console.WriteLine(testObj2.j);
|
||||
Test testObj3 = Activator.CreateInstance(testType, 99, "111222") as Test;//两个个参数的有参构造函数
|
||||
Console.WriteLine(testObj3.str);
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
}
|
||||
}
|
||||
}
|
||||
//总结
|
||||
//反射
|
||||
//在程序运行时,通过反射可以得到其他程序集或者自己的程序集代码的各种信息
|
||||
//类、函数、变量、对象等等,实例化他们,执行他们,操作他们
|
||||
|
||||
//关键类
|
||||
//Type
|
||||
//Assembly
|
||||
//Activator
|
||||
|
||||
//对于我们的意义
|
||||
//在初中级阶段 基本不会使用反射
|
||||
//所以目前对于大家来说,了解反射可以做什么就行
|
||||
//很长时间内都不会用到反射相关知识点
|
||||
|
||||
//为什么要学反射
|
||||
//为了之后学习Unity引擎的基本工作原理做铺垫
|
||||
//Unity引起的基本工作机制 就是建立在反射的基础上
|
||||
@@ -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,23 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace Lesson20_反射练习
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Assembly assembly = Assembly.LoadFrom(@"D:\VisualStudio2022\VisualStudio Programe\C#\C#进阶\反射练习库\bin\Debug\反射练习库.dll");
|
||||
Type[] types = assembly.GetTypes();
|
||||
Console.WriteLine("______________");
|
||||
for (int i = 0; i < types.Length; i++)
|
||||
{
|
||||
Console.WriteLine(types[i]);
|
||||
}
|
||||
Console.WriteLine("______________");
|
||||
Type player = assembly.GetType("反射练习库.Player");
|
||||
|
||||
object obj = Activator.CreateInstance(player);
|
||||
Console.WriteLine(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,182 @@
|
||||
using System.Diagnostics;
|
||||
using System.Runtime.CompilerServices;
|
||||
|
||||
namespace Lesson21_特性
|
||||
{
|
||||
#region 知识点一 特性是什么
|
||||
//特性是一种允许我们向程序的程序集添加元数据的语言结构
|
||||
//它是用于保存程序结构信息的某种特殊类型的类
|
||||
|
||||
//特性提供功能强大的方法以将声明信息与 C# 代码(类型、方法、属性等)相关联。
|
||||
//特性与程序实体关联后,即可在运行时使用反射查询特性信息
|
||||
|
||||
//特性的目的是告诉编译器把程序结构的某组元数据嵌入程序集中
|
||||
//它可以放置在几乎所有的声明中(类、变量、函数等等申明)
|
||||
|
||||
//说人话:
|
||||
//特性本质是个类
|
||||
//我们可以利用特性类为元数据添加额外信息
|
||||
//比如一个类、成员变量、成员方法等等为他们添加更多的额外信息
|
||||
//之后可以通过反射来获取这些额外信息
|
||||
#endregion
|
||||
|
||||
#region 知识点二 自定义特性
|
||||
//继承特性的基类 Attribute
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Field, AllowMultiple = true, Inherited = false)]
|
||||
class MyCustomAttribute : Attribute
|
||||
{
|
||||
//特性中的成员 一般根据需求来写
|
||||
public string info;
|
||||
public MyCustomAttribute(string info)
|
||||
{
|
||||
this.info = info;
|
||||
}
|
||||
public void TestFunc()
|
||||
{
|
||||
Console.WriteLine("特性的方法");
|
||||
}
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 知识点三 特性的使用
|
||||
//基本语法
|
||||
//[特性名(参数列表)]
|
||||
//本质上 就是在调用特性类的构造函数
|
||||
//写在哪里?
|
||||
//类、函数、变量上一行,表示他们具有该特征信息
|
||||
|
||||
[MyCustom("额外信息例如说明")]
|
||||
[MyCustom("额外信息例如说明")]
|
||||
class MyClass
|
||||
{
|
||||
[MyCustom("12312321")]
|
||||
public int value;
|
||||
|
||||
public void TestFunc(int a)
|
||||
{
|
||||
|
||||
}
|
||||
//[MyCustom("这是用来计算的函数")]
|
||||
//public void TestFunc([MyCustom("函数参数")]int a)
|
||||
//{
|
||||
|
||||
//}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 知识点四 限制自定义特性的使用范围
|
||||
//通过为特性类 加特性 限制其使用范围
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true, Inherited = true)]
|
||||
//参数一:AttributeTargets — 特性嫩个用在哪些地方
|
||||
//参数二:AllowMultiple — 是否允许多个特性实例用在同一个目标上
|
||||
//参数三:Inherited — 特性是否能被派生类和重写成员继承
|
||||
public class MyCustom2Attribute : Attribute
|
||||
{
|
||||
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 知识点五 系统自带特性——过时特性
|
||||
//过时的特性
|
||||
//Obsolete
|
||||
//用于提示用户 使用的方法等成员已经过时 建议使用新方法
|
||||
//一般加在函数前的特性
|
||||
|
||||
class TestClass
|
||||
{
|
||||
//参数一:调用过时方法时 提示的内容
|
||||
//参数二: true-使用该方法时会报错 false-使用该方法时直接警告
|
||||
[Obsolete("OldSpeak方法已经过时了,请使用Speak方法", false)]
|
||||
public void OldSpeak(string str)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
public void Speak()
|
||||
{
|
||||
|
||||
}
|
||||
public void SpeakCaller(string str, [CallerFilePath] string fileName = "",
|
||||
[CallerLineNumber] int line = 0, [CallerMemberName] string target = "")
|
||||
{
|
||||
Console.WriteLine(str);
|
||||
Console.WriteLine(fileName);
|
||||
Console.WriteLine(line);
|
||||
Console.WriteLine(target);
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region 知识点六 系统自带特性——调用者信息特征
|
||||
//哪个文件调用?
|
||||
//CallerFilePath特性
|
||||
//哪一行调用?
|
||||
//CallerLineNumber特性
|
||||
//哪个函数调用?
|
||||
//CallerMemberName特性
|
||||
|
||||
//需要引用命名空间 using System.Runtime.CompilerServices;
|
||||
//一般作为函数参数的特性
|
||||
#endregion
|
||||
|
||||
#region 知识点七 系统自带特性——条件编译特性
|
||||
//条件编译特性
|
||||
//Conditional
|
||||
//它会和预处理指令 #define配合使用
|
||||
|
||||
//需要引用命名空间using System.Diagnostics;
|
||||
//主要可以用在一些调试代码上
|
||||
//有时想执行有时不想执行的代码
|
||||
#endregion
|
||||
|
||||
#region 知识点八 系统自带特性——外部Dll包函数特性
|
||||
//DllImport
|
||||
//用来标记非.Net(C#)的函数,表明该函数在一个外部的DLL中定义。
|
||||
//一般用来调用 C或者C++的Dll包写好的方法
|
||||
//需要引用命名空间 using System.Runtime.InteropServices
|
||||
#endregion
|
||||
class Program
|
||||
{
|
||||
[Conditional("Func")]
|
||||
static void Func()
|
||||
{
|
||||
Console.WriteLine("Func执行");
|
||||
}
|
||||
static void Main(string[] args)
|
||||
{
|
||||
#region 特性的使用
|
||||
MyClass c = new MyClass();
|
||||
Type t = c.GetType();
|
||||
//t.Assembly.GetType();
|
||||
//t = typeof(MyClass);
|
||||
//t = Type.GetType("Lesson21_特性.MyClass");
|
||||
|
||||
//判断是否使用了某个特性
|
||||
//参数1:特性的类型
|
||||
//参数2:代表是否搜索继承链(属性和事件忽略此参数)
|
||||
if (t.IsDefined(typeof(MyCustomAttribute), false) )
|
||||
{
|
||||
Console.WriteLine("该类型应用了MyCustomAttribute特性");
|
||||
}
|
||||
|
||||
//获取Type元数据中的所有特性
|
||||
object[] array = t.GetCustomAttributes(true);
|
||||
for (int i = 0; i < array.Length; i++)
|
||||
{
|
||||
if (array[i] is MyCustomAttribute)
|
||||
{
|
||||
Console.WriteLine((array[i] as MyCustomAttribute).info);
|
||||
(array[i] as MyCustomAttribute).TestFunc();
|
||||
}
|
||||
}
|
||||
#endregion
|
||||
TestClass tc = new TestClass();
|
||||
tc.OldSpeak("1123");
|
||||
tc.Speak();
|
||||
tc.SpeakCaller("123123");
|
||||
|
||||
Func();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -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,43 @@
|
||||
using System.Reflection;
|
||||
|
||||
namespace Lesson21_特性练习
|
||||
{
|
||||
internal class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
Assembly assembly = Assembly.LoadFrom(@"D:\VisualStudio2022\VisualStudio Programe\C#\C#进阶\反射练习库\bin\Debug\反射练习库");
|
||||
Type[] types = assembly.GetTypes();
|
||||
for (int i = 0; i < types.Length; i++)
|
||||
{
|
||||
Console.WriteLine(types[i]);
|
||||
}
|
||||
//得type
|
||||
Type playertype = assembly.GetType("反射练习库.Player");
|
||||
//实例化对象
|
||||
object playerObj = Activator.CreateInstance(playertype);
|
||||
Console.WriteLine(playerObj);
|
||||
|
||||
FieldInfo[] fields = playertype.GetFields();
|
||||
for (int i = 0; i < fields.Length; i++)
|
||||
{
|
||||
Console.WriteLine(fields[i]);
|
||||
}
|
||||
|
||||
//首先得到自定义特性的Type
|
||||
Type atrribute = assembly.GetType("反射练习库.MyCustomAttribute");
|
||||
|
||||
//赋值名字
|
||||
FieldInfo fieldStr = playertype.GetField("name");
|
||||
if(fieldStr.GetCustomAttribute(atrribute) != null)
|
||||
{
|
||||
Console.WriteLine("非法操作,随意修改name成员");
|
||||
}
|
||||
else
|
||||
{
|
||||
//检测是否被自定义特性修饰 如果是 就不能更改 而是提示
|
||||
fieldStr.SetValue(playerObj, "123123");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("反射练习库")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("反射练习库")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2025")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("86839643-1a23-454e-8b06-839900b3e032")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,41 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace 反射练习库
|
||||
{
|
||||
class MyCustomAttribute: Attribute
|
||||
{
|
||||
|
||||
}
|
||||
public struct Position
|
||||
{
|
||||
public int x;
|
||||
public int y;
|
||||
|
||||
public Position(int x,int y)
|
||||
{
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
}
|
||||
}
|
||||
public class Player
|
||||
{
|
||||
[MyCustom()]
|
||||
public string name;
|
||||
public int hp;
|
||||
public int atk;
|
||||
public int def;
|
||||
public Position position;
|
||||
public Player()
|
||||
{
|
||||
name = "英雄";
|
||||
hp = 100;
|
||||
atk = 10;
|
||||
def = 5;
|
||||
position = new Position(0, 0);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,48 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>{86839643-1A23-454E-8B06-839900B3E032}</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>反射练习库</RootNamespace>
|
||||
<AssemblyName>反射练习库</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Core" />
|
||||
<Reference Include="System.Xml.Linq" />
|
||||
<Reference Include="System.Data.DataSetExtensions" />
|
||||
<Reference Include="Microsoft.CSharp" />
|
||||
<Reference Include="System.Data" />
|
||||
<Reference Include="System.Net.Http" />
|
||||
<Reference Include="System.Xml" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="test.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace 测试类库
|
||||
{
|
||||
//纯写代码类库,没有任何运行代码
|
||||
//没法点击运行,只能在项目中右键生成,这样就有dll文件了
|
||||
public class HK
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,33 @@
|
||||
using System.Reflection;
|
||||
using System.Runtime.CompilerServices;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
// 有关程序集的一般信息由以下
|
||||
// 控制。更改这些特性值可修改
|
||||
// 与程序集关联的信息。
|
||||
[assembly: AssemblyTitle("测试类库")]
|
||||
[assembly: AssemblyDescription("")]
|
||||
[assembly: AssemblyConfiguration("")]
|
||||
[assembly: AssemblyCompany("")]
|
||||
[assembly: AssemblyProduct("测试类库")]
|
||||
[assembly: AssemblyCopyright("Copyright © 2025")]
|
||||
[assembly: AssemblyTrademark("")]
|
||||
[assembly: AssemblyCulture("")]
|
||||
|
||||
// 将 ComVisible 设置为 false 会使此程序集中的类型
|
||||
//对 COM 组件不可见。如果需要从 COM 访问此程序集中的类型
|
||||
//请将此类型的 ComVisible 特性设置为 true。
|
||||
[assembly: ComVisible(false)]
|
||||
|
||||
// 如果此项目向 COM 公开,则下列 GUID 用于类型库的 ID
|
||||
[assembly: Guid("70c2e0d7-1f4a-4442-af1c-3b1c2475b748")]
|
||||
|
||||
// 程序集的版本信息由下列四个值组成:
|
||||
//
|
||||
// 主版本
|
||||
// 次版本
|
||||
// 生成号
|
||||
// 修订号
|
||||
//
|
||||
[assembly: AssemblyVersion("1.0.0.0")]
|
||||
[assembly: AssemblyFileVersion("1.0.0.0")]
|
||||
@@ -0,0 +1,54 @@
|
||||
<?xml version="1.0" ?>
|
||||
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
|
||||
<PropertyGroup>
|
||||
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
|
||||
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
|
||||
<ProjectGuid>70c2e0d7-1f4a-4442-af1c-3b1c2475b748</ProjectGuid>
|
||||
<OutputType>Library</OutputType>
|
||||
<AppDesignerFolder>Properties</AppDesignerFolder>
|
||||
<RootNamespace>测试类库</RootNamespace>
|
||||
<AssemblyName>测试类库</AssemblyName>
|
||||
<TargetFrameworkVersion>v4.7.2</TargetFrameworkVersion>
|
||||
<FileAlignment>512</FileAlignment>
|
||||
<Deterministic>true</Deterministic>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
<DebugSymbols>true</DebugSymbols>
|
||||
<DebugType>full</DebugType>
|
||||
<Optimize>false</Optimize>
|
||||
<OutputPath>bin\Debug\</OutputPath>
|
||||
<DefineConstants>DEBUG;TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
|
||||
<DebugType>pdbonly</DebugType>
|
||||
<Optimize>true</Optimize>
|
||||
<OutputPath>bin\Release\</OutputPath>
|
||||
<DefineConstants>TRACE</DefineConstants>
|
||||
<ErrorReport>prompt</ErrorReport>
|
||||
<WarningLevel>4</WarningLevel>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System"/>
|
||||
|
||||
<Reference Include="System.Core"/>
|
||||
<Reference Include="System.Xml.Linq"/>
|
||||
<Reference Include="System.Data.DataSetExtensions"/>
|
||||
|
||||
|
||||
<Reference Include="Microsoft.CSharp"/>
|
||||
|
||||
<Reference Include="System.Data"/>
|
||||
|
||||
<Reference Include="System.Net.Http"/>
|
||||
|
||||
<Reference Include="System.Xml"/>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Class1.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
</Project>
|
||||
Reference in New Issue
Block a user