什么是委托
委托是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。 委托对方法的引用的,委托实例调用方法。
委托的声明
使用委托可以直接使用.NetFramework已经定义的委托,也可以自定义。自定义委托是用delegate声明,编译器在使用 delegate关键字时生成的代码自动会继承MulticastDelegate 类的成员的方法调用。
使用delegate自定义的委托
示例演示了一个委托声明:
public delegate int PerformCalculation(int x, int y);
框架的委托
Action 类型,Action委托的变体可包含多达 16 个参数,它的返回类型都是void,示例演示:
public delegate void Action();
public delegate void Action<in T>(T arg);
public delegate void Action<in T1, in T2>(T1 arg1, T2 arg2);
Func 类型,Func委托是带有返回值的,示例演示:
public delegate TResult Func<out TResult>();
public delegate TResult Func<in T1, out TResult>(T1 arg);
public delegate TResult Func<in T1, in T2, out TResult>(T1 arg1, T2 arg2);
还有一种专门的委托类型 Predicate,此类型返回单个值的测试结果:
public delegate bool Predicate<in T>(T obj);
委托的使用
委托的使用有三种方法:函数申明,匿名方法,Labmda表达式
多播委托
委托对象的一个有用属性在于可通过使用 + 运算符将多个对象分配到一个委托实例。 多播委托包含已分配委托列表。 此多播委托被调用时会依次调用列表中的委托。 仅可合并类型相同的委托。- 运算符可用于从多播委托中删除组件委托。示例演示:
delegate void CustomDel(string s);
public class TestClass
{
static void Hello(string s)
{
Console.WriteLine($"Hello,{s}");
}
static void Goodbye(string s)
{
Console.WriteLine($"Goodbye,{s}");
}
static void Main()
{
CustomDel hiDel, byeDel, multiDel, multiMinusHiDel;
hiDel = Hello;
byeDel = Goodbye;
multiDel = hiDel + byeDel;
multiMinusHiDel = multiDel - hiDel;
Console.WriteLine("Invoking delegate hiDel:");
hiDel("A");
Console.WriteLine("Invoking delegate byeDel:");
byeDel("B");
Console.WriteLine("Invoking delegate multiDel:");
multiDel("C");
Console.WriteLine("Invoking delegate multiMinusHiDel:");
multiMinusHiDel("D");
}
}
/* Output:
Invoking delegate hiDel:
Hello, A!
Invoking delegate byeDel:
Goodbye, B!
Invoking delegate multiDel:
Hello, C!
Goodbye, C!
Invoking delegate multiMinusHiDel:
Goodbye, D!
*/
事件
事件是委托的一个实例,而且这个实例带一个event关键字修饰。event主要是限制权限,它只允许在事件声明类里面去invoke和赋值,不允许外面,甚至子类操作。
用委托的多播来实现“猫叫人醒鼠跑”,先定义猫鼠人三个实体:
public class People
{
public void Awake()
{
Console.WriteLine($"{this.GetType().Name} Awake");
}
}
public class Mouse
{
public void Run()
{
Console.WriteLine($"{this.GetType().Name} Run");
}
}
public class Cat
{
public void Roar()
{
Console.WriteLine($"{this.GetType().Name} Roar");
}
public Action CatRoarAction;
}
用委托实现就是多播委托的添加和调用:
Cat cat = new Cat();
cat.Roar();
cat.CatRoarAction += new People().Awake;
cat.CatRoarAction += new Mouse().Run;
cat.CatRoarAction.Invoke();
/* Output:
Cat Roars
People Awake
Mouse Rur
*/
多播委托与事件不同是它可以在定义类的外面Invoke和赋值:
cat.CatRoarAction.Invoke();
cat.CatRoarAction = null;
使用事件(event)来实现“猫叫人醒鼠跑”,要把猫中的委托改成事件,也就是加个event,因为事件就是一个用evnet修饰的委托实例。修改后:
public class Cat
{
public void Roar()
{
Console.WriteLine($"{this.GetType().Name} Roar");
}
public event Action CatRoarEvent;
public void CatRoar()//事件不能在定义类外面使用
{
this.CatRoarEvent?.Invoke();
}
}
事件的实现必然用到发布订阅模式,在这里猫是发布者,鼠与人是订阅者,事件的使用就是先订阅,然后发布。事件的订阅与发布
Cat cat = new Cat();
cat.Roar();
cat.CatRoarEvent += new People().Awake;
cat.CatRoarEvent += new Mouse().Run;
cat.CatRoar();
/* Output:
Cat Roars
People Awake
Mouse Rur
*/
参考
https://www.cnblogs.com/foolishfox/archive/2010/09/16/1827964.html
https://docs.microsoft.com/zh-cn/dotnet/csharp/delegates-strongly-typed
本文介绍了C#中的委托,包括其作为方法引用的特性,如何声明自定义和使用预定义的委托类型如Action和Func。重点探讨了多播委托,展示了如何通过+运算符合并多个委托实例,并通过事件(event)进行权限控制。通过“猫叫人醒鼠跑”的示例,解释了多播委托与事件在实现上的差异,并阐述了事件的订阅和发布模式。

1641

被折叠的 条评论
为什么被折叠?



