C#-委托的详细用法

什么是委托

委托是一种函数引用的Object,实际上是用类完成了函数指针的功能

C#中的委托(Delegate)类似于C或C++中函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。

委托(Delegate)特别用于实现事件和回调方法。所有的委托(Delegate)都派生 自System.Delegate 类。

说人话就是委托是一种引用类型,它可以用来引用一个或多个方法,并且也可以将方法作为参数传递给其他方法,或者将方法作为返回值类型返回。

委托的使用

1,声明委托:

Delegate void Print(int x)

2,初始化,给委托赋值

  • 方法1:Print someFunc=hello;
  • 方法2:Print someFunc=new Print(hello);

3,调用委托变量

SomeFunc(x);

委托的分类

  • 委托静态方法:委托一个静态方法
  • 委托实例方法:委托一个实例方法

委托的原理

委托是将函数指针和实例对象打包在一起的类,它有两个重要的成员,一个用来保存实例对象,一个用来保存函数的指针。从源码中可以查看System.Delegate

 我们查看System.Delegate的属性,可以看到一个属性Target

public Object Target
{
    get
    {
        return GetTarget();
    }
}

看一下GetTarget的功能

internal virtual Object GetTarget()
{
    return (_methodPtrAux.IsNull())?_target:null;
}

意思就是当把一个静态方法给委托的时候将会返回一个null,如果是一个实例方法时, 将会返回当前方法所在的实例对象(this)

下面用一段代码演示一下:

using System;
//声明委托
public delegate void Print(int x);
namespace ConsoleApp1
{
    public class Test
    {
        //实例方法
        public void Test1(int x)
        {
            Console.WriteLine("实例方法,数字:{0}",x);
        }
        //静态方法
        public static void Test2(int x)
        {
            Console.WriteLine("静态方法,数字:{0}",x);
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //委托的使用
            Test t = new Test();//实例对象
            Print p1 = new Print(t.Test1);//委托赋值
            p1(25);//调用委托
            Print p2 = Test.Test2;//委托赋值
            p2(33);//调用委托
            //委托原理
            Console.WriteLine(p1.Target is Test);//实例方法-判断Target是不是指向方法所在的对象
            Console.WriteLine(p2.Target is Test);//静态方法-判断Target是不是null
            Console.ReadLine();
        }
    }
}

输出结果

实例方法,数字:25
静态方法,数字:33
True
False

也就是如果Target属性为null说明是静态方法的委托,如果不为null说明是实例方法的 委托

需要注意的是声明的委托类型和被委托的函数类型以及参数要一致,如果委托没有返回 值,那么被委托的函数也要没有返回值,如果委托有参数,那么被委托的函数和委托的 参数类型要一致。

如果这个还不是很好理解的话,下面我们再看一段代码

using System;

// 定义一个委托类型
public delegate void MyDelegate(string message);

public class DelegateExample
{
    // 一个接受委托作为参数的方法
    public void ProcessMessage(string message, MyDelegate callback)
    {
        // 处理消息
        Console.WriteLine("Processing message: " + message);
        // 调用委托,传递消息
        callback(message);
    }
}

public class Program
{
    // 一个方法作为委托的实例
    public static void DisplayMessage(string message)
    {
        Console.WriteLine("Displaying message: " + message);
    }

    public static void Main()
    {
        DelegateExample example = new DelegateExample();//创建一个实例
        // 创建委托实例并传递方法引用
        MyDelegate delegateInstance = new MyDelegate(DisplayMessage);
        // 调用方法,并将委托作为参数传递
        example.ProcessMessage("Hello, World!", delegateInstance);
    }
}

输出结果

Processing message: Hello, World!
Displaying message: Hello, World!
请按任意键继续. . .

我们首先定义了一个名为 MyDelegate 的委托类型,它可以引用一个带有 string 类型参数和无返回值的方法,或者接收一个也是参数也是String类型的方法。

然后,我们创建了一个包含 ProcessMessage 方法的类,该方法接受一个字符串和一个委托作为参数,然后调用传入的委托并传递消息。

最后,在 Main 方法中,我们创建了一个委托实例MyDelegate,并将一个DisplayMessage方法引用传递给它,然后将这个委托实例作为参数传递给 ProcessMessage 法。

注意:将方法传递给委托时,此方法和委托的形参要一致,也就是传入的参数要一致。

所以在32行将委托作为参数传递给ProcessMessage的时候,首先输出Processing message:hello,然后调用委托,在之前我们已经将DisplayMessage传递给了委托,所以在调用委托时,会调用DisplayMessage方法。

通过这两个代码就可以很直白的看出委托的作用,就是将方法封装在委托中,然后就可以将委托对象传递给可调用所引用方法的代码,不必在编译时知道将要调用那个方法。(这样应该就清楚了吧,在看不懂就说不过去了)。

通常委托和事件一起使用来构成发布-订阅模式,或者叫观察者模式。

系统内置委托

前面是自己定义的委托,但是系统也提供了两种委托:Action和Func,Action用于不需 要返回值的委托,Func适合需要返回值的委托

Action委托

1,Action委托 封装一个方法,该方法不具有参数并且不返回值

2,Action<T>委托 封装一个方法,该方法只有一个参数并且不返回值

3,Action<T1,T2>委托 封装一个方法,该方法具有两个参数并且不返回值

最多有16个参数

Func委托

1,Func(TResult)委托封装封装一个不具有参数但却返回 TResult 参数指定的类型值的方 法

2,Func(T,TResult)委托 封装一个具有一个参数并返回 TResult 参数指定的类型值的方法

3,Func(T1,T2,TResult)委托 封装一个具有两个参数并返回 TResult 参数指定的类型值的方 法

其中的T是参数类型,TResult是返回值类型

下面用一个例子演示:

using System;

namespace ConsoleApp1
{
    public class Test
    {
        //Action示例
        public void Test1(int x)
        {
            Console.WriteLine("打印数字:"+x);
        }
        //Func示例
        public int Test2(int n)
        {
            return n;
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //系统内置委托的使用
            Test t = new Test();//实例对象
            Action<int> ac1 = new Action<int>(t.Test1);//委托赋值
            ac1(22);//调用委托
            Func<int, int> ac2 = new Func<int, int>(t.Test2);//委托赋值
            Console.WriteLine(ac2(233));//调用委托
            Console.ReadLine();
        }
    }
}

输出结果:

打印数字:22
233

多播委托

多播委托是指在一个委托中注册多个方法,在注册方法时可以在委托中使用加号运算符

或者减号运算符来实现添加或撤销方法。

比如现实的点餐系统,可以点甜食,面食,水果等,在这里委托相当于点餐平台,每一 个类型的商品可以理解为在委托商注册的一个方法。

使用委托的这个有用的特点,可以创建一个委托被调用时要调用的方法的调用列表。 这被称为委托的 多播(multicasting),也叫组播。

下面的程序演示了委托的多播:

using System;

//声明委托
public delegate void Order();
namespace ConsoleApp1
{
    public class Test
    {
        //买水果
        public void Test1()
        {
            Console.WriteLine("购买水果!");
        }
       //买甜食
       public static void Test2()
        {
            Console.WriteLine("购买甜食!");
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            //多播委托
            Test t = new Test();//实例对象
            Order order =new Order(t.Test1);//委托赋值-实例方法
            order += new Order(Test.Test2);//委托赋值-静态方法
            order();//调用委托
            Console.ReadLine();
        }
    }
}

输出结果:

购买水果!
购买甜食!

通过这个例子可以看出来,我们把两个方法都注册到了一个委托上面,并且调用委托一 下调用了两个方法,先调用了购买水果的方法,然后调用了购买甜食的方法。

在使用多播委托时需要注意,在委托中注册的方法参数列表必须与委托定义的参数列表 相同,否则不能将方法添加到委托上。

如有错漏之处,敬请指正!

  • 5
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
C# 委托是一种类型,它允许将方法作为参数传递给其他方法或存储在变量中。委托常用于事件处理程序、回调函数和多线程编程等场景,以下是 C# 委托用法: 1.定义委托类型 可以使用 `delegate` 关键字定义一个委托类型,例如: ``` delegate void MyDelegate(string message); ``` 上面的代码定义了一个委托类型 `MyDelegate`,它可以引用一个参数为字符串类型、返回值为 void 的方法。 2.创建委托对象 可以使用 `new` 关键字创建一个委托对象,例如: ``` MyDelegate myDelegate = new MyDelegate(MyMethod); ``` 上面的代码创建了一个委托对象 `myDelegate`,它引用方法 `MyMethod`。 3.调用委托对象 可以使用委托对象调用它所引用的方法,例如: ``` myDelegate("Hello, world!"); ``` 上面的代码调用了委托对象 `myDelegate` 引用的方法,并传入参数。 4.多播委托 委托可以组合成多个方法的调用,形成一个多播委托。可以使用加法运算符将多个委托组合成一个新的委托,例如: ``` MyDelegate myDelegate1 = new MyDelegate(MyMethod1); MyDelegate myDelegate2 = new MyDelegate(MyMethod2); MyDelegate myDelegate3 = myDelegate1 + myDelegate2; ``` 上面的代码创建了三个委托对象,并将前两个委托对象组合成一个新的委托对象 `myDelegate3`。 5.使用内置委托类型 C# 还提供了一些内置的委托类型,例如 `Func`、`Action`、`Predicate` 等。可以直接使用这些内置委托类型,无需定义新的委托类型。例如: ``` Func<int, int, int> myFunc = (x, y) => x + y; int result = myFunc(1, 2); // result = 3 ``` 上面的代码使用内置委托类型 `Func` 定义了一个接收两个 int 类型参数并返回 int 类型结果的委托对象 `myFunc`,并使用 lambda 表达式实现了方法体。 以上就是 C# 委托的基本用法

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

真的没事鸭

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

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

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

打赏作者

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

抵扣说明:

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

余额充值