C# 委托定义和多播委托到事件的区别与使用

本文介绍了C#中的委托,包括其作为方法引用的特性,如何声明自定义和使用预定义的委托类型如Action和Func。重点探讨了多播委托,展示了如何通过+运算符合并多个委托实例,并通过事件(event)进行权限控制。通过“猫叫人醒鼠跑”的示例,解释了多播委托与事件在实现上的差异,并阐述了事件的订阅和发布模式。
什么是委托

委托是一种引用类型,表示对具有特定参数列表和返回类型的方法的引用。 委托对方法的引用的,委托实例调用方法。

委托的声明

使用委托可以直接使用.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

https://docs.microsoft.com/zh-cn/dotnet/csharp/programming-guide/delegates/how-to-combine-delegates-multicast-delegates

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值