C# 委托和事件(委托)

回调(callback)函数是Windows编程的一个重要部分。C或C++编程背景,在许多Windows API中使用过回调。VB添加AddressOf关键字后,开发人员就可以利用以前一度受到限制的API。回调函数实际上是方法调用的指针也称为函数指针。.NET以委托的形式实现函数指针的概念。C中函数指针只不过是一个指向存储单元的指针,无法说出这个指针实际指向什么,像参数和返回类型等更不知晓。

委托

当要把方法传送给其他方法时,需要使用委托。
①启动线程——在C#中,可以告诉计算机并性运行某些新的执行序列。这种序列称为线程,在基类System.Threading.Thread的一个实例上使用方法Start(),就可以开始执行一个线程。如果要告诉计算机开始一个新的执行序列,就必须说明要在哪里执行该序列。必须为计算机提供开始执行的方法的细节,即Thread.Start()方法必须带有一个参数,该参数定义要由线程调用的方法。
②调用库类——有许多库包含执行各种标准任务的代码。
③事件—一般是通过内置代码发生什么事件,GUI编程主要处理事件。在发生事件时,运行库需要知道应执行哪个方法。

void EntryPoint()
{
    //do whatever the thread needs to do
}

Thread NewThread=new Thread();
Thread.Start(EntryPoint);

如果要传递方法,就必须把方法的细节封装在一种新类型的对象中,即委托。委托只是一种特色的对象类型,其特殊之处在于,定义的所有对象都包含数据,而委托包含的只是方法的细节。

在C#中声明委托

在C#中使用一个类时分为两个阶段:①定义这个类,即告诉编译器该类时由声明字段和方法组成;(除非只使用静态方法)实例化类的一个对象。使用委托时,也需要经过这两个步骤。
委托的使用方法:①定义它时哪个委托类型;②创建该委托的一个或多个实例。

定义委托的语法如下:

delegate void VoidOperation(uint x);

在定义委托时,必须给出它所代表的方法的全部细节。
理解委托的一种号方式是把委托的作用当作是给方法签名指定名称。
实际上,"定义一个委托"是指”定义一个新类“。委托实现为派生于基类System.MulticastDelegate的类,System.MulticastDelegate又派生于基类System.Delegae.

在C#中使用委托

下面代码说明如何使用委托。

private delegate string GetAString();

static void Main(string[] args)
{
    int x=40;
    GetAString firstStringMethod=new GetAString(x.Tostring());
    Console.WriteLine("String is"+firstStringMethod());
    //With firstStringMethod initialized to.x.ToString(),
    //the above startment is equivalent to saying
    //Consoles.writeLine("String is"+x.ToString());

    struct Current
    {
        public uint Dollars;
        public ushort Cents;

        public Currency(uint dollars,ushort cents)
        {
            this.Dollars=dollars;
            this.Cents=cents;
        }

        public override string ToString()
        {
            return string.Format("${0}.{1,-2:00}",Dollars,Cents);
        }

        public static explicit operator Currency(float value)
        {
            return value.Dollars+(value.Cents/100.0f);
        }
    }

    struct Currency
    {
        public static string GetCurrencyUnit()
        {
            return "Dollars";
        }

        private delegate string GetAString();

        static void Main(string[] args)
        {
            int x=40;
            GetAString firstStringMethod=new GetAString(x.ToString);
            Console.WriteLine("String is"+firstStringMethod());
            Currency balance=new Currency(35,40);
            firstStringMethod=new GetAString(balance.ToString);
            Console.WriteLine("String is"+firstStringMethod());
            firstStringMethod=new GetAString(Currency.GetCurrencyUnit);
            Console.WriteLine("String is"+firstStringMethod());
        }
    }
}

给定委托实例可以表示任何类型的任何对象上的实例方法或静态方法——只要方法的签名匹配于委托的签名即可。
上述代码说明:如何通过委托来调用方法,重新给委托指定在类的不通实例上执行不同方法,设置可以指定静态方法,或者在类的不同类型的实例上执行的方法,只要每个方法的签名匹配于委托定义即可。

##Action和Func委托
泛型Action委托表示引用一个void返回类型的方法。没有泛型参数的Action类可调用没有参数的方法。Action调用带一个参数的方法,Action<in T1,in T2>调用带两个参数的方法,Action<in T1,in T2,in T2,in T4,in T5,in T6,in T7,inT8>调用带8个参数的方法。
Func委托可以类似的方式使用。Func允许调用带返回类型的方法。FunC委托类型可以调用带返回类型且无参数的方法,Func<in T,out TResult>调用带一个参数的方法,Func<in T1,in T2,in T3,in T4,out TResult>调用带4个参数的方法。可以声明一个该委托类型的变量,或者该委托类型的数组,如下所示:

Func<double,double>[] operations=
{
    MathOperations,MultiplyByTwo,
    MathOperations,Square
};

多播委托

如果要调用多个方法,就需要多次显式调用这个欸托,委托也可以包含多个方法,这种委托称为多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。对此,委托的签名就必须返回void;否则,就只能得到委托调用的最后一个结果。
可以使用返回类型为void的Action委托:
MathOperations.cs类代码

using System;

public static class MathOperations
{
    public static void MultiplyByTwo(double value) =>
        Console.WriteLine($"Multiplying by 2: {value} gives {value * 2}");

    public static void Square(double value) =>
        Console.WriteLine($"Squaring: {value} gives {value * value}");
}

主控制台程序代码:

using System;

Action<double> operations = MathOperations.MultiplyByTwo;
operations += MathOperations.Square;

ProcessAndDisplayNumber(operations, 2.0);
ProcessAndDisplayNumber(operations, 7.94);
ProcessAndDisplayNumber(operations, 1.414);

void ProcessAndDisplayNumber(Action<double> action, double value)
{
    Console.WriteLine($"ProcessAndDisplayNumber called with value = {value}");
    action(value);
    Console.WriteLine();
}

源代码下载:腾讯云盘
https://share.weiyun.com/k60Yncqj

匿名方法

匿名方法是用作委托的参数的一段代码。

using System;

string mid = ", middle part,";

Func<string, string> anonDel = delegate (string param)
{
    param += mid;
    param += " and this was added to the string.";
    return param;
};

Console.WriteLine(anonDel("Start of string"));

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

钢铁男儿

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值