我的编程空间,编程开发者的网络收藏夹
学习永远不晚

C#中的委托怎么声明和使用

短信预约 -IT技能 免费直播动态提醒
省份

北京

  • 北京
  • 上海
  • 天津
  • 重庆
  • 河北
  • 山东
  • 辽宁
  • 黑龙江
  • 吉林
  • 甘肃
  • 青海
  • 河南
  • 江苏
  • 湖北
  • 湖南
  • 江西
  • 浙江
  • 广东
  • 云南
  • 福建
  • 海南
  • 山西
  • 四川
  • 陕西
  • 贵州
  • 安徽
  • 广西
  • 内蒙
  • 西藏
  • 新疆
  • 宁夏
  • 兵团
手机号立即预约

请填写图片验证码后获取短信验证码

看不清楚,换张图片

免费获取短信验证码

C#中的委托怎么声明和使用

这篇“C#中的委托怎么声明和使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C#中的委托怎么声明和使用”文章吧。

如果要给方法传递一个方法参数时,就可以使用委托。要传递方法,就必须把方法的细节封装在一钟新类型的对象中,即委托。委托是一种特殊类型的对象,其特殊之处在于,我们以前定义的所有对象都包含数据,而委托只包含一个或多个方法的地址。
.NET版本中,委托指向方法的地址。在C++中,函数指针是一个指向内存位置的指针,但它不是类型安全的。开发者无法判断这个指针实际指向什么,像参数和返回值等项就更不知道了。
.NET委托是类型安全的类,它定义了返回类型和参数的类型。委托类不仅包含对方法的引用,也可以包含对多个方法的引用。

1.声明委托

使用委托和使用类一样,也需要经过定义和实例化两个步骤。首先必须定义要使用的委托,对于委托,定义它就是告诉编译器这种类型的委托表示哪种类型的方法。然后,必须创建该委托的一个或多个实例才能使用。编译器在后台将创建表示该委托的一个类。
定义委托的语法:

delegate void IntMethod(int x);//定义了一个委托IntMethod,指定该委托的每个实例都可以包含一个或多个方法的引用,引用的方法必须带有一个int参数,并返回void.

因为定义委托基本上是定义一个新类,所以可以在定义类的任何地方定义委托。也可以在委托的定义上使用修饰符:public,private,protected等。
委托派生自基类System.MulticastDelegate,MulticastDelegate又派生自基类System.Delegate.
类有两个不同的术语:“类”表示广义的定义,“对象”表示;类的实例。但委托只有一个术语。在创建委托的实例时,所创建的实例仍称为委托。必须从上下文中确定委托的具体含义。

2.使用委托

定义好委托之后,就可以创建它的一个实例,从而用它存储特定方法的细节。

delegate void IntMethod(int x);        static void Fun(int x)        {            Console.WriteLine(x);        }        static void Main()        {          int x = 40;          IntMethod intMethod = new IntMethod(Fun);          intMethod(x);          Console.ReadKey();        }

委托在语法上总是接受一个参数的构造函数,这个参数就是委托引用的方法。这个方法必须匹配最初定义委托时的签名。
使用委托实例的名称,后面加上圆括号,如果需要参数就必须在圆括号内加上参数。
给委托实例提供圆括号和调用委托类的Invoke()方法完全相同:

  intMethod(x);  intMethod.Invoke(x);

为了减少输入量,只需要给委托实例传递方法地址的名称就可以,这称为委托推断。

IntMethod intMethod = new IntMethod(Fun);IntMethod intMethod =Fun;

委托推断可以在需要委托实例的任何地方使用。委托推断也可以用于事件,因为事件基于委托。(事件后面文章有介绍)
注意,使用委托可以调用任何类型对象的方法,不管是静态方法还是实例方法。

3.使用委托数组

//先在一个类中定义两个方法:          class MathOperations          {            public static double MultiplyByTwo(double value)            {              return value * 2;            }            public static double Square(double value)            {              return value * value;            }          }
//定义一个返回double类型且带有double类型参数的委托          delegate double DoubleOp(double x);                    class Program          {            static void Main()            {              //实例化委托数组,和实例化类的数组一样              DoubleOp[] operations =              {                MathOperations.MultiplyByTwo,                MathOperations.Square              };                            //遍历数组,使用数组中的每个委托实例              for (int i = 0; i < operations.Length; i++)              {                Console.WriteLine("Using operations[{0}]:", i);                //将委托实例作为参数传递给ProcessAndDisplayNumber方法                ProcessAndDisplayNumber(operations[i], 2.0);                ProcessAndDisplayNumber(operations[i], 7.94);                ProcessAndDisplayNumber(operations[i], 1.414);                Console.WriteLine();              }            }            static void ProcessAndDisplayNumber(DoubleOp action, double value)            {              //在ProcessAndDisplayNumber中调用委托,执行委托实例引用的方法              double result = action(value);              Console.WriteLine(                 "Value is {0}, result of operation is {1}", value, result);            }          }

4.Action<T>和Func<T>委托

除了为每个参数和返回类型定义一个委托类型之外,还可以使用Action<T>和Func<T>委托。
泛型Action<T>委托表示引用一个void返回类型的方法。这个委托类存在不同的变体,可以传递最多16种不同的参数类型。没有泛型参数的Action类调用没有参数的方法。Action<in T>调用带一个参数的方法,Action<in T1,in T2>调用带两个参数的方法,依次类推。
Func<T>委托允许调用带返回类型的方法。与Action<T>类似,Func<T>也存在不同的变体,可以传递最多16种不同的参数类型和一个返回类型。Func<out TResult>委托类型可以调用无参数且带返回类型的方法。
下面使用Func<T>委托实现一个不使用委托很难编写的一个功能:给对象数组排序,如果对象是int或string这样值类型的对象会容易排序,如果是要排序很多自定义的类型的对象,需要编写大量代码。使用委托会减少代码量。
定义包含比较方法的类:
BubbleSorter类实现了一个泛型方法 Sort<T>,第一个参数是要排序的对象数组,第二个是一个委托,传递比较两个对象的方法。这样可以给Sort<T>方法,传递自定义的比较方法。

class BubbleSorter          {            static public void Sort<T>(IList<T> sortArray, Func<T, T, bool> comparison)            {              bool swapped = true;              do              {                swapped = false;                for (int i = 0; i < sortArray.Count - 1; i++)                {                  //调用委托中引用的方法,比较两个对象                  if (comparison(sortArray[i + 1], sortArray[i]))                  {                    T temp = sortArray[i];                    sortArray[i] = sortArray[i + 1];                    sortArray[i + 1] = temp;                    swapped = true;                  }                }              } while (swapped);            }          }

定义自定义的一个类

class Employee          {            public Employee(string name, decimal salary)            {              this.Name = name;              this.Salary = salary;            }            public string Name { get; private set; }            public decimal Salary { get; private set; }            public override string ToString()            {              return string.Format("{0}, {1:C}", Name, Salary);            }            public static bool CompareSalary(Employee e1, Employee e2)            {              return e1.Salary < e2.Salary;            }          }

客户端代码:

Employee[] employees =          {            new Employee("Bugs Bunny", 20000),            new Employee("Elmer Fudd", 10000),            new Employee("Daffy Duck", 25000),            new Employee("Wile Coyote", 1000000.38m),            new Employee("Foghorn Leghorn", 23000),            new Employee("RoadRunner", 50000)          };            //Sort执行了自定义的Employee.CompareSalary方法          BubbleSorter.Sort(employees, Employee.CompareSalary);          foreach (var employee in employees)          {            Console.WriteLine(employee);          }

5.多播委托

前面介绍的每个委托只包含一个方法的调用,委托也可以包含多个方法。这种委托称为多播委托。
如果调用多播委托,就可以按顺序调用多个方法,但如果委托的签名不是返回void,就只能得到委托调用的最后一个方法的结果。
使用+=添加方法,-=删除方法。

static void Main()        {          Action<double> operations = MathOperations.MultiplyByTwo;          operations += MathOperations.Square;          ProcessAndDisplayNumber(operations, 2.0);          ProcessAndDisplayNumber(operations, 7.0);          Console.WriteLine();        }        static void ProcessAndDisplayNumber(Action<double> action, double value)        {          Console.WriteLine();          Console.WriteLine("ProcessAndDisplayNumber called with value = {0}", value);          action(value);        }                class MathOperations          {            public static void MultiplyByTwo(double value)            {              double result = value * 2;              Console.WriteLine("Multiplying by 2: {0} gives {1}", value, result);            }            public static void Square(double value)            {              double result = value * value;              Console.WriteLine("Squaring: {0} gives {1}", value, result);            }          }

每次调用ProcessAndDisplayNumber方法,都会按顺序调用action委托实例中的两个方法。
输出:

  ProcessAndDisplayNumber called with value = 2  Multiplying by 2: 2 gives 4  Squaring: 2 gives 4  ProcessAndDisplayNumber called with value = 7  Multiplying by 2: 7 gives 14  Squaring: 7 gives 49

委托还可以使用+,-运算符:

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

多播委托包含一个逐个调用的委托集合。如果其中一个方法抛出异常,整个迭代就会停止。

  static void One()  {    Console.WriteLine("One");    throw new Exception("Error in one");  }  static void Two()  {    Console.WriteLine("Two");  }  static void Main()  {    Action d1 = One;    d1 += Two;    try    {      d1();    }    catch (Exception)    {      Console.WriteLine("Exception caught");    }  }

委托只调用了第一个方法。因为第一个方法抛出异常,委托的迭代停止,不再调用Two()方法。
避免这个问题,可以使用Delegate类定义的GetInvocationList()方法,它返回一个Delegate对象数组:

  Action d1 = One;  d1 += Two;  Delegate[] delegates = d1.GetInvocationList();  foreach (Action d in delegates)  {    try    {      d();    }    catch (Exception)    {      Console.WriteLine("Exception caught");    }  }

输出:

  One  Exception caught  Two

使用GetInvocationList()方法可以为委托的每个方法传递不同的参数,获取每个方法的返回值。

  static int One(int x)  {    return x;  }  static int Two(int x)  {    return x;  }  static void Main()  {    Func<int,int> d1 = One;    d1 += Two;    Delegate[] delegates = d1.GetInvocationList();    Func<int, int> d2 = (Func<int, int>)delegates[0];    Console.WriteLine( d2(1));    Func<int, int> d3 = (Func<int, int>)delegates[1];    Console.WriteLine(d3(2));    Console.ReadKey();  }

输出:

  1  2

6.匿名方法

使用匿名方法可以将方法体直接赋给委托实例,而不需要定义一个方法。

  static void Main()  {    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"));  }

上面代码不是把方法名赋给委托变量anonDel,而是一段代码,它前面是关键字delegate和参数列表。在使用匿名方法时,可以使用外部变量。
匿名方法的优点是减少了代码量。使用匿名方法,代码执行速度并没有加快。编译器仍定义了一个方法,该方法只有一个自动指定的名称。
使用匿名方法,必须遵守两条规则:

  • (1).在匿名方法中不能使用跳转语句(break,goto,continue)调到匿名方法的外部,外部的代码也不能调到匿名方法内部。

  • (2).匿名方法内部不能访问不安全的代码。也不能在匿名方法使用ref和out

如果需要匿名方法多次编写同一个功能时,就不要用匿名方法了。

以上就是关于“C#中的委托怎么声明和使用”这篇文章的内容,相信大家都有了一定的了解,希望小编分享的内容对大家有帮助,若想了解更多相关的知识内容,请关注编程网行业资讯频道。

免责声明:

① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

C#中的委托怎么声明和使用

下载Word文档到电脑,方便收藏和打印~

下载Word文档

猜你喜欢

C#中的委托怎么声明和使用

这篇“C#中的委托怎么声明和使用”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“C#中的委托怎么声明和使用”文章吧。如果要给方
2023-06-30

C#中怎么使用委托和事件

在 C# 中,委托和事件是一种常用的机制,用于实现事件驱动的编程模型。委托是一种类型,用于存储对方法的引用,而事件是委托的一种特殊用法,用于通知其他代码发生了某个特定的动作。下面是一个简单的示例,演示了如何在 C# 中定义和使用委托和事件
C#中怎么使用委托和事件
2024-03-06

C#委托怎么使用

这篇文章主要介绍了C#委托怎么使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇C#委托怎么使用文章都会有所收获,下面我们一起来看看吧。1、什么是委托从数据结构来讲,委托是和类一样是一种用户自定义类型。委托是方
2023-06-29

C#中的委托怎么定义和应用

今天小编给大家分享一下C#中的委托怎么定义和应用的相关知识点,内容详细,逻辑清晰,相信大部分人都还太了解这方面的知识,所以分享这篇文章给大家参考一下,希望大家阅读完这篇文章后有所收获,下面我们一起来了解一下吧。一、概述委托为引用类型二、使用
2023-06-30

C#委托的使用方法是什么

在C#中,委托是一种类型,用于引用一个或多个方法。委托可以看作是函数指针,它可以被用来调用方法。使用委托的步骤如下:定义委托:首先需要定义一个委托类型,指定委托可以引用的方法签名。例如:delegate void MyDelegate(i
C#委托的使用方法是什么
2024-03-06

C#线程委托BeginInvoke与EndInvoke怎么使用

这篇文章主要讲解了“C#线程委托BeginInvoke与EndInvoke怎么使用”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“C#线程委托BeginInvoke与EndInvoke怎么使用
2023-07-02

详解C#中委托的概念与使用

委托这个名字取的神乎其神的,但实质是函数式编程,把函数作为参数传递给另一个参数。这篇文章主要为大家介绍一下C#中委托的概念与使用,需要的可以参考一下
2023-02-27

Go中的channel怎么声明和使用

这篇文章主要介绍了Go中的channel怎么声明和使用的相关知识,内容详细易懂,操作简单快捷,具有一定借鉴价值,相信大家阅读完这篇Go中的channel怎么声明和使用文章都会有所收获,下面我们一起来看看吧。channelGo语言中的通道(c
2023-07-05

C#方法中的反射方式和委托方式怎么用

这篇文章主要介绍C#方法中的反射方式和委托方式怎么用,文中介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要看完!在开发过程中对静态方法的调用是通过类型名后面加个点而后是调用方法的名称,对类型实例方法的调用是通过new一个对象,而后
2023-06-17

C#中事件和委托的区别是什么

事件是一种特殊的委托,委托是一种类型安全的函数指针,而事件是委托的一种封装,它只能在其所在的类中被触发和订阅。委托可以被任何类访问,任何类都可以触发和订阅委托,而事件只能在其所在的类中被触发和订阅。另外,事件可以通过关键字+=和-=来添
C#中事件和委托的区别是什么
2024-04-03

C#中如何使用委托和事件处理程序

C#中如何使用委托和事件处理程序,需要具体代码示例在C#中,委托和事件处理程序是两个非常重要的概念,它们可以用于实现事件驱动的编程模型。委托提供了一种将方法作为参数传递的机制,而事件处理程序则用于处理特定事件的方法。本文将详细介绍C#中如何
2023-10-22

C#中委托的概念与使用方法是什么

本篇内容主要讲解“C#中委托的概念与使用方法是什么”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“C#中委托的概念与使用方法是什么”吧!委托的概念委托这个名字取的神乎其神的,但实质是函数式编程,把
2023-07-05

C#中怎么利用委托实现异步调用

这篇文章将为大家详细讲解有关C#中怎么利用委托实现异步调用,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。委托实现C#异步调用的步骤:1.定义委托。2.将要进行异步调用的方法“实例化”到定义的
2023-06-17

Perl中怎么声明和使用变量

在Perl中,可以使用my关键字来声明变量。变量名以$符号开头,可以是任意的字母、数字和下划线的组合。例如:my $name = "Alice";my $age = 30;要使用变量,只需要直接使用变量名即可。例如:print "My
Perl中怎么声明和使用变量
2024-03-05

C++的using声明和using编译指令怎么使用

这篇文章主要介绍“C++的using声明和using编译指令怎么使用”,在日常操作中,相信很多人在C++的using声明和using编译指令怎么使用问题上存在疑惑,小编查阅了各式资料,整理出简单好用的操作方法,希望对大家解答”C++的usi
2023-06-22

C#中怎么声明变量和常量

在C#中声明变量和常量的方式如下:声明变量:// 声明一个整型变量int num;// 声明并初始化一个字符串变量string name = "Alice";// 声明一个浮点型变量并赋值float salary;salary
C#中怎么声明变量和常量
2024-03-06

VB中委托和事件是怎么工作的

在VB中,委托和事件通常一起使用来实现事件驱动编程。委托是一种类型,可以用来引用方法,事件是一种特殊类型的委托,用于通知类中的其他对象或模块发生了某种事件。具体来说,当一个对象触发了一个事件时,它会调用与该事件关联的委托。其他对象可以订阅
VB中委托和事件是怎么工作的
2024-04-03

C++ 中如何声明和使用友元函数?

c++++ 中的友元函数是一种可访问其他类私有/受保护成员的特殊函数。声明友元函数时需使用 friend 关键字,如:声明友元函数:friend void printvalue(const myclass& obj);使用友元函数:友元函数
C++ 中如何声明和使用友元函数?
2024-04-12

编程热搜

  • Python 学习之路 - Python
    一、安装Python34Windows在Python官网(https://www.python.org/downloads/)下载安装包并安装。Python的默认安装路径是:C:\Python34配置环境变量:【右键计算机】--》【属性】-
    Python 学习之路 - Python
  • chatgpt的中文全称是什么
    chatgpt的中文全称是生成型预训练变换模型。ChatGPT是什么ChatGPT是美国人工智能研究实验室OpenAI开发的一种全新聊天机器人模型,它能够通过学习和理解人类的语言来进行对话,还能根据聊天的上下文进行互动,并协助人类完成一系列
    chatgpt的中文全称是什么
  • C/C++中extern函数使用详解
  • C/C++可变参数的使用
    可变参数的使用方法远远不止以下几种,不过在C,C++中使用可变参数时要小心,在使用printf()等函数时传入的参数个数一定不能比前面的格式化字符串中的’%’符号个数少,否则会产生访问越界,运气不好的话还会导致程序崩溃
    C/C++可变参数的使用
  • css样式文件该放在哪里
  • php中数组下标必须是连续的吗
  • Python 3 教程
    Python 3 教程 Python 的 3.0 版本,常被称为 Python 3000,或简称 Py3k。相对于 Python 的早期版本,这是一个较大的升级。为了不带入过多的累赘,Python 3.0 在设计的时候没有考虑向下兼容。 Python
    Python 3 教程
  • Python pip包管理
    一、前言    在Python中, 安装第三方模块是通过 setuptools 这个工具完成的。 Python有两个封装了 setuptools的包管理工具: easy_install  和  pip , 目前官方推荐使用 pip。    
    Python pip包管理
  • ubuntu如何重新编译内核
  • 改善Java代码之慎用java动态编译

目录