Compare commits

..

10 Commits

Author SHA1 Message Date
Kister 7ca83872f3 添加Lesson21 2025-11-05 10:39:06 +08:00
Kister ed22d4bcbd 添加Lesson20 2025-10-24 21:47:11 +08:00
Kister 0fa8be7459 添加Lesson19 2025-10-23 21:00:25 +08:00
Kister f77c10f1d5 添加Lesson18 2025-10-23 18:12:21 +08:00
Kister a79f6fcf42 添加Lesson17 2025-10-22 10:35:50 +08:00
Kister faee796928 添加Lesson16 2025-10-21 20:37:12 +08:00
Kister b1d4959956 添加Lesson15 2025-10-20 11:12:14 +08:00
Kister b4d3ced472 添加Lesson14 2025-10-20 09:23:46 +08:00
Kister be8eb0f422 添加Lesson13 2025-10-17 11:48:41 +08:00
Kister 657a23e681 添加Lesson12 2025-10-17 10:27:36 +08:00
49 changed files with 2685 additions and 0 deletions
+132
View File
@@ -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
+10
View File
@@ -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>
+25
View File
@@ -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>
+178
View File
@@ -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>
+117
View File
@@ -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>
+102
View File
@@ -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>
+52
View File
@@ -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>
+124
View File
@@ -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>
+146
View File
@@ -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>
+86
View File
@@ -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>
+125
View File
@@ -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>
+23
View File
@@ -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>
+182
View File
@@ -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>
+43
View File
@@ -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")]
+41
View File
@@ -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>
+14
View File
@@ -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")]
+54
View File
@@ -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>