C#之委托

委 托 委托


C#委托之类间互调函数


委托的作用:双方的信息的桥接(因为双方直接传递信息存在障碍)

程序中的问题:有时候一个对象,想访问另一个对象,可能正常情况下无法达到要求。

特别是两个对象相互调用,你中有我,我中有你,就会无限循环,卡死。也编译不过。

所以面向对象编程中,我们使用对象的时候,要特别注意对象之间消息的传递问题。

但如果我必须完成这个两个类对象互相获取对方函数的需求,怎么办?

委托诞生了。(有人会想到静态方法,但是静态方法有时候是不可行的)

程序中的委托(delegate):是一种程序特性,这种特性是针对方法而言的。也就说委托是方法的指针(代表),换句话说,方法可以作为参数传递。

委托的基本使用

【1】声明委托类型:定义一个方法的原型(方法返回值类型、参数类型和个数)
【2】定义委托方法
【3】创建委托变量
【4】关联委托变量(3,4可以合并在一起)
【5】使用委托变量

1.public delegate void TestDelegate(int a ,int b);
2.static void Add(){}
3.TestDelegate  testDele = null;
4.testDele += Add;
5.testDele(100,200)

委托的动态关联
+=
-=
如果我们想去掉一个方法的关联,直接用-=即可。这个在委托和事件中非常有用。


委托的应用

  1. 如果一个委托关联了多个方法,当我们使用委托变量的时候,会按照关联方法的顺序,依次调用方法。这种委托,我们称为多路委托(多播委托)

委托与多态(委托类型作为方法参数)

static void Test3(calculatorDelegate1 myDelegate){
	//基于委托实现多态的话,方法需要的参数,会在这个地方获取....
	myDelegate(6.6,9.99); // 看这个你根本不知道你对这两个数做什么操作
}

实际开发中下面的多态实现一般和上面不在一起

static void CallTest3(0{
Test3(Add);//直接将一个方法作为参数传递过去
Test3(delegate(double a,double b){ print("test") })
}


系统委托

系统委托使用:我们知道,如果我们想将方法作为参数传递,你必须要首先声明委托!

其实,我们声明的委托,无非就是没有参数、一个参数,多个参数;有返回值,没有返回值。

实际开发中,你如果用的委托非常多,你就得不断的声明各种委托。

针对有返回值的,和没有返回值的情况。
平台给我们提供了两种系统委托,可以直接使用。Action 和 Func

不需要再声明委托。而是直接使用ActionFunc

public void Add(double a ,double b)
{
   a + b
}
Action<double, double> myAction = Add; //使用系统委托直接声明我们需要的“委托”

myAction(2.3,4.6);

委托多态的实现可以改成系统委托

在基于委托实现多态的时候,更加方便

static void Test2(Action<double, double> myAction){

)


委托在多线程中的应用

委托学习关系链:自定义委托–>系统委托–>匿名方法–>Lambda表达式–>多线程应用


委托,和类、接口、int、string一样属于一种类型


委托是引用类型


委托(Delegate)是存有对某个方法的引用的一种引用类型变量。


引用可在运行时被改变。用于将方法作为参数传递给其他方法


委托是一个类,它定义了方法的类型


换句说法:委托是一个类,它定义了方法的类型(比如String类,定义了字符串的类型),使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用lf- Else(Switch)语句,同时使得程序具有更好的可扩展性。

需要注意的是在定义时参数类型和个数要与你想委托的方法一致。


使用委托可以将多个方法绑定到同个委托变量,当调用此变量时(这里用“调用”这个词,是因为此变量代表一个方法),可以依次调用所有绑定的方法

在这里插入图片描述


1.方法的描述

委托,delegate ,是C#中一种回调的实现
-对应C++/Qt里的槽


C#委托的四种形式(delegate、Action、Func、predicate)

(1)delegate

Delegate至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型。

public delegate int MethodDelegate(int x, int y);
private static MethodDelegate method;
static void Main(string[] args)
{
    method = new MethodDelegate(Add);
    Console.WriteLine(method(60,20));
    Console.ReadKey();
}

private static int Add(int x, int y)
{
    return x + y;
}

(2)Action

Action是无返回值的泛型委托。至少0个参数,至多16个参数,无返回值

static void Main(string[] args)
{
   Test<string>(Action,"Hello World!");
   Test<int>(Action, 1000);
   Test<string>(p => { Console.WriteLine("{0}", p); }, "Hello World");//使用Lambda表达式定义委托
   Console.ReadKey();
}
public static void Test<T>(Action<T> action, T p)
{
   action(p);
}
private static void Action(string s)
{
   Console.WriteLine(s);
}
private static void Action(int k)
{
   Console.WriteLine(k);
}

(3)Func

Func是有返回值的泛型委托。 Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可void。

(4) predicate

predicate 是返回bool型的泛型委托。Predicate有且只有一个参数,返回值固定为bool


在C#里面,如何描述一个方法呢?
1 参数类型列表
2 返回值类型
比如,

public void test1(int a)

“一个参数为(int)的、返回值为void的方法”

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharp基础语法
{
    public class Example
    {
       public void test1(int a)
        {
            Console.WriteLine("test1:" + a);
        }

        public void test2(int b)
        {
            Console.WriteLine("test2:" + b);
        }

        public int test3(int m)
        {
            Console.WriteLine("test3:" + m);

            return m * m;
        }

        public int test4(int a)
        {
            Console.WriteLine("test4:" + a);
            return a + a;
        }

        public int test5(int x,int y)
        {
            return x + y;
        }
    }
}

1对test1(), test2(), test3(), test4(), test5()进行描述
2对此五个方法进行规类
可以发现,test1,test2同属一类,test3,test4同属一类

2.委托 delegate

委托,delegate,是一个对方法类型的描述

例如:

public delegate void DFunction(int a);

则DFunction类型指的是“一种参数为(int)、返回值为void的方法”

类比一下,会更易懂:

public class Student{}
public interface Player{}
public delegate void DFunction (int a);

其中,delegate声明它是个委托类型,DFunction是类型的名字。


一个委拖对象,就是一个方法的实例例如:

DFurction d = new DFunction(ex.test1);
d(18);

传参时,要指定某个对象的某个方法


using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharp基础语法
{
    public class Example
    {
       public void test1(int a)
        {
            Console.WriteLine("test1:" + a);
        }

        public void test2(int b)
        {
            Console.WriteLine("test2:" + b);
        }

        public int test3(int m)
        {
            Console.WriteLine("test3:" + m);

            return m * m;
        }

        public int test4(int a)
        {
            Console.WriteLine("test4:" + a);
            return a + a;
        }

        public int test5(int x,int y)
        {
            return x + y;
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharp基础语法
{
    // 第一类方法
    public delegate void NumberOneFunction(int a);
    // 第二类方法
    public delegate int NumberTwoFunction(int b);
    // 第三类方法
    public delegate int NumberThreeFunction(int a, int b);
    class Program
    {
        static void Main(string[] args)
        {
            Example ex = new Example();

            NumberOneFunction num1 = new NumberOneFunction(ex.test1);
            num1(18); // == ex.test1(18)


         }
    }
}


3.委拖的更多用法

1委托的调用,以下两种方式等效:

DogFunction dog =new DogFunction(ex.Test);
dog(18);
dog.Invoke(18);

其中:dog是一个委托(方法),dog(18)就是调用这个方法,dog.Invoke(18)也是调个方法。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharp基础语法
{
    public class Example
    {
      // 实例方法
      public void Test(int a)
        {
            Console.WriteLine("Test:" + a);
        }

        // 静态方法
        public static void Print(int a)
        {
            Console.WriteLine("Print:" + a);
        }
    }
}

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace CSharp基础语法
{
    // 第一类方法
    public delegate void NumberOneFunction(int a);

    class Program
    {
        static void Main(string[] args)
        {
            Example ex = new Example();

            // 实例方法的调用
            NumberOneFunction num1 = new NumberOneFunction(ex.Test);
            num1(100);
            num1.Invoke(100);

             静态方法的调用
            NumberOneFunction num11 = new NumberOneFunction(Example.Print);
            num11(1100);
            num11.Invoke(1100);

        }
    }
}


在这里插入图片描述


3委拖是一种类型,可以和 class, interiface同级定义

public delegate void DFunction (int a);
public class YourClass {};

也可以作为内部类型

public class YourClass{
public delegate void DFunction (int a);}

全称:YourNameSpace.YourClass.DFunction


委托应该类似于C/C++里的函数指针数组,在函数传参时传递的是函数指针,在调用的时候通过指针访问这个函数。

首先需要明白函数的本质:函数的本质是一段可执行性代码段。函数名,则是指向这段代码段的首地址。

函数指针:包含了代码段的首地址,返回类型,和传入参数


函数指针和回调函数

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值