C#笔记-1(委托机制和事件机制)
前言
C#自学笔记,主要记录一些重要的C#特征内容,对于大多数编程语言相通相似的部分不再记录,本笔记便于快速回顾c#的语法特点
一、几种基础的委托结构(Delegate)
- 自定义委托 语法: delegate 返回类型 委托名([参数]);
- Action内置委托 语法: Action<[参数类型0-16个]> 委托名=被委托方法名;
- Func内置委托 语法: Function<[参数类型0-16个],返回类型> 委托名=被委托方法名;
- 多播委托 语法:委托名+=被委托方法名;委托名-=被委托方法名;
class Program
{
//自定义委托方法
delegate void P(Object str);
static void Main(string[] args)
{
/*
自定义委托两种实现
*/
P p = new P(Console.WriteLine);
p("自定义 构造 传被委托方法的结果");
P p2 = Console.WriteLine;
p2("自定义 赋值被委托方法的结果");
/*
Action为内置的委托,只能委托 无参数 且无返回值的方法
*/
Action a = printHelloWorld;
Action b = printHelloWorld2;
a();
b();
/*
Action<T1,T2...>泛型委托为内置的委托
允许委托带参数(0-16个参数) 且无返回值的方法
*/
Action<String, String> c=printString2;
c("WOS","WOSB");
/*
Func<[ParamsType...],ResultType>为内置委托
允许委托带参数(0-16个参数,最后一个为返回值类型)且有返回值的方法 Func<[ParamsType,...],ResultType>
*/
Func<String> d = funcMethod1;
Func<int, String> e = funcMethod2;
Console.WriteLine(d());
Console.WriteLine(e(222));
/*
多播委托
委托引用+=被委托方法(执行委托时会多运行多个被委托的方法)
委托引用-=被委托方法 (执行委托时不会运行减少的被委托的方法)
*/
Action f = printHelloWorld;
f +=printHelloWorld2;
f();
f -= printHelloWorld2;
f();
/*
当委托方法中没有被委托方法时,委托方法会指向null,所以运行多播委托前最好检查是否为空
*/
if (f!=null) {
f();
}
/*
lamda 匿名委托方法
*/
Func<String, String> g = (arg1) =>
{
return "回调结果:"+arg1;
};
Console.WriteLine(g("测试请求"));
/*
监听输入传入委托中
*/
string str = Console.ReadLine();
p(str);
//阻塞cms,任意键释放
Console.ReadKey();
}
public static void printHelloWorld()
{
Console.WriteLine("Hello world");
}
public static void printHelloWorld2()
{
Console.WriteLine("Hello world2");
}
public static void printString2(String a,String b) {
Console.WriteLine("A:"+a+",B:"+b);
}
public static String funcMethod1() {
return "配置载入信息";
}
public static String funcMethod2(int param) {
return "params is " + param;
}
}
二、事件(Event)
- 语法: event 事件名(即委托方法名) 事件变量名;
- 主要用于发布/订阅机制,只能在发布对象中执行,但可以在外部进行+= -=订阅,通常用于观察者模式,一种特殊的委托
- 事件的命名规范通常以Event结尾
如下为资源加载的示例
观察者模式
流程:我起床(被观察者/发布者)->家里的猫猫们开始动作(观察者/订阅者)
//主程序
class Program
{
static void Main(string[] args)
{
Player1 player1 = new Player1("我");
new Cat("东月","从被窝里钻出来喵喵叫",player1);
new Cat("十五", "从猫窝里跑了出来喵喵叫", player1);
player1.GetUp();
}
}
玩家/我 被观察者
class Player1
{
private String name;
public event Action Player1GetUpEvent;
public Player1() { }
public Player1(string name)
{
this.name = name;
}
public void GetUp() {
Console.WriteLine(name+"起床了!");
/*
发布
*/
if (Player1GetUpEvent!=null) {
Player1GetUpEvent();
}
}
}
猫猫观察者
class Cat
{
private String name;
//动作
private String action;
//被观察者/发布者对象
private Player1 player1;
public Cat() { }
public Cat(string name, string action, Player1 player1)
{
this.name = name;
this.action = action;
this.player1 = player1;
//订阅
player1.Player1GetUpEvent += catAction;
}
//观察者/订阅者执行动作
public void catAction() {
Console.WriteLine(name+":"+action);
}
}
执行结果
我起床了!
东月:从被窝里钻出来喵喵叫
十五:从猫窝里跑了出来喵喵叫
事件机制可能用到的场景举一反三
释放技能(发布事件)->多个敌人掉血(订阅事件)
点击开始游戏(发布事件)->多个资源管理器开始载入(订阅事件)
人物在水中超过60s(发布事件)->开始持续掉血、状态异常(订阅事件)
猫草罐被打开(发布事件)->猫猫们迅速靠近(订阅事件)
…
总结
委托和事件的区别:
委托通常用于回调而事件通常用在发布订阅机制中,如观察者模式
委托可以在任何能引用的地方执行而事件只能在事件所在的对象执行(防止重复调用)