C#委托

C# 委托简述 使用关键字delegate声明委托除了使用delegate定义 委托以外C#提供两个定义好的泛型委托Action与Func) (当然你也可以使用delegate自定义泛型委托)这里先介绍两个C#定义的委托,相信很多人都在使用,不管你清不清楚什么是委托Action:是无返回值的泛型委托。下面action 表示无参,无返回值的委托//定义委托action();//使用方式1//使用方式2Console.WriteLine("我是传入的无参无返回值的委托方法"); 阅读详情

在C和C++ 中,只能提取函数的地址,并作为一个参数传递它。C没有类型安全性。可以把任何函数传递给需要函数指针的方法。但是,这种直接方法不仅会导致一些关于类型安全性的问题,而且没有意识到:在进行面向对象编程时,几乎没有方法是孤立存在的,而是在调用方法前通常需要与类实例相关联。所以.NET FmmewOrk在语法上不允许使用这种直接方法。如果要传递方法,就必须把方法的细节封装在一种新类型的对象中,即委托。委托只是一种特殊类型的对象,其特殊之处在于,我们以前定义的所有对象都包含数据,而委托包含的只是一个或多个方法的地址。



1.声明委托

定义委托的语法如下:

delegate void MyMethodInvoker(int x);

在这个示例中,定义了一个委托MyMethodInvoker,并指定该委托的每个实例都可以包含一个方法的引用,该方法带有一个int参数,并返回void。理解委托的一个要点是它们的类型安全性非常高。在定义委托时,必须给出它所表示的方法的签名和返回类型等全部细节。

假设要定义一个返回值为string不带参数的委托,可以编写如下代码:

delegate string MyMethodInvoker();

根据定义的可见性,和委托的作用域,可以在委托的定义上应用任意常见的访问修饰符:public、private、protected等:
public delegate string MyMethodInvoker();


2.使用委托

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

private delegate string GetAString();
        static void Main()
        {
            int x = 40;
            GetAString firststringMethod = new GetAString(x.ToString);
            Console.WriteLine("string is (0)", firststringMethod());
        }
在这段代码中,实例化了类型为GetAString的一个委托,并对它进行了初始化,使它引用整型变量x的ToString方法。。在C#中,委托在语法上总是接受一个参数的构造函数,这个参数就是委托引用的方法。这个方法必须匹配最初定义委托时的签名。

实际上,给委托实例提供圆括号与调用委托类的Invoke方法完全相同。因为firststringMethod是委托类型的一个变量,所以C#编译器会用firststringMethod.Invoke()代替firststringMethod()。

为了减少输入量,只要需要委托实例,就可以只传送地址的名称,这称为委托推断,只要编译器可以把委托实例解析为特定的类型,这个C#特性就是有效的。所以上面的委托初始化也可简写为:

GetAString firststringMethod=x.ToString;


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

除了为每个参数和返回类型定义一个新委托类型之外,还可以使用Action<T>和Func<T>委托。泛型Action<T>委托表示引用一个vod返回类型的方法。因为这个委托类存在不同的变体,所以可以传递至多16种不同的参数类型。没有泛型参数的Action类可调用没有参数的方法。Action<T>调用带一个参数的方法,Action<T1,T2>调用带两个参数的方法

Func<T>可以以类似的方式使用,Func<T>允许调用带返回类型的方法。。与Action<T>类似,Func<T>也定义了不同的变体,至多也可以传递16个参数类型和一个返回类型。Func<out TResult>委托类型可以调用带返回类型且无参数的方法,Func<T,out TResult>调用带一个参数的方法。

所以之前自定义的委托GetAString也可以用Func<T>代替。

Func<string> firststringMethod=x.ToString;


4.Bubblesorter示例

下面的示例将说明委托的真正用途。我们要编写一个类Bubblesorter,它实现一个静态方法Sort(),这个方法的第一个参数是一个对象数组,把该数组按照升序重新排列。

要实现对任何类型的对象数组排序,就必须要实现泛型方法Sort<T>(),另外该方法还需一个比较函数,其两个参数的类型是T,返回值为bool。因此,可以跟Sort<T>()指定如下签名:

static public void Sort<T>(IList<T> array,Func<T,T,bool> comparison);

下面定义Bubblesorter类:

class Bubblesorter
    {
        static public void Sort<T>(IList<T> array, Func<T, T, bool> comparison)
        {
            bool swapped = true;
            do
            {
                swapped = false;
                for (int i = 0; i < array.Count; i++)
                {
                    if (comparison(array[i + 1], array[i]))
                    {
                        swapped = true;
                        T tmp = array[i + 1];
                        array[i + 1] = array[i];
                        array[i] = tmp;
                    }
                }
            } while (swapped);
        }
    }
为了使用Bubblesorter类,下面再定义一个Employee类。

class Employee
    {
        public string Name { get; private set; }
        public float Salary { get; private set; }
        public Employee(string name, float salary)
        {
            Name = name;
            Salary = salary;
        }
        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;
        }
    }

注意,为了匹配Func<T,T,bool>委托的签名,在这个类中必须定义CompareSalary,它的参数是两个Employee引用,并返回一个布尔值。

下面编写客户端代码,完成程序。

static void Main()
        {
            Employee[] employee ={
                                     new Employee("小王",4000),
                                     new Employee("小赵",3200),
                                     new Employee("小韩",3500),
                                     new Employee("小宋",5000)
                                };
            Bubblesorter.Sort<Employee>(employee, Employee.CompareSalary);
            foreach (Employee e in employee)
            {
                Console.WriteLine(e);
            }
        }

运行这段代码,结果如下:

5.多播委托

前面使用的每个委托都只包含一个方法调用。调用委托的次数与调用方法的次数相同。如果要调用多个方法,就需要多次显式调用这个委托。但是,委托也可以包含多个方法。这种委托称为多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的签名就必须返回void,否则,就只能得到委托调用的最后一个方法的结果。

多播委托可以识别运算符+和+=,另外多播委托还识别-和-=,以从委托中删除方法调用。

为了说明多播委托的用法,下面定义一个MathOperation类,它可以做两个整型数的相加和想减。

class MathOperation
    {
        public static void Add(int a,int b)
        {
            Console.WriteLine("{0}+{1}={2}",a,b,a+b);
        }
        public static void Sub(int a, int b)
        {
            Console.WriteLine("{0}-{1}={2}", a, b, a - b);
        }
    }

下面测试多播委托

static void Main()
        {
            Action<int, int> action = MathOperation.Add;
            action += MathOperation.Sub;
            action(5, 3);
            //从action中删除MathOperation.Sub
            action -= MathOperation.Sub;
            action(5, 3);
        }

运行程序,结果如下:

如果正在使用多播委托,就应知道对同一个委托调用方法链的顺序并未正式定义。因此应避免编写依赖于以特定顺序调用方法的代码。

通过一个委托调用多个方法还可能导致一个大问题。多播委托包含一个逐个调用的委托集合。如果通过委托调用的其中一个方法抛出一个异常,整个迭代就会停止。

为了说明这种情况,下面修改MathOperation类,在Add中抛出异常。

class MathOperation
    {
        public static void Add(int a,int b)
        {
            Console.WriteLine("{0}+{1}={2}",a,b,a+b);
            throw new Exception();
        }
        public static void Sub(int a, int b)
        {
            Console.WriteLine("{0}-{1}={2}", a, b, a - b);
        }
    }

然后在主函数中也稍作修改

static void Main()
        {
            Action<int, int> action = MathOperation.Add;
            action += MathOperation.Sub;
            try
            {
                action(5, 3);
            }
            catch
            {
                Console.WriteLine("抛出异常……");
            }
        }

运行结果为:

委托只调用了Add方法。因为Add方法抛出了一个异常,所以委托的迭代会停止。

在这种情况下,为了避免这个问题,应自己迭代方法列表。Delegate类定义GetInvocationList方法,它返回一个Delegate对象数组。现在可以使用这个委托调用与委托直接相关的方法,捕获异常,并继续下一次迭代。

static void Main()
        {
            Action<int, int> action = MathOperation.Add;
            action += MathOperation.Sub;
            foreach (Action<int, int> d in action.GetInvocationList())
            {
                try
                {
                    d(5, 3);
                }
                catch
                {
                    Console.WriteLine("抛出异常……");
                }
            }
            
        }

修改了代码后运行应用程序,会看到在捕获了异常后,将继续迭代下一个方法。

6.匿名方法

到目前为止,要想使委托工作,方法必须己经存在(即委托是用它将调用的方法的相同签名定义的)。但还有另外一种使用委托的方式:即通过匿名方法。匿名方法是用作委托的参数的一段代码。

用匿名方法定义委托的语法与前面的定义并没有区别。但在实例化委托时,就有区别了。下面是一个非常简单的控制台应用程序,它说明了如何使用匿名方法:

static void Main()
        {
            Action<int, int> action = delegate(int a,int b)
            {
                Console.WriteLine("{0}+{1}={2}",a,b,a+b);
            };
            action(5, 3);
        }






C# 委托 在 C# 中,委托(Delegate)是一种类型安全的函数指针,它允许将方法作为参数进行传递,并在不同的上下文中调用这些方法。委托提供了一种灵活的方式来实现事件处理、回调机制和异步编程等功能,极大地增强了 C# 语言的功能性和可扩展性。委托是一种引用类型,它定义了方法的签名。委托可以指向任何具有相同签名的方法。这个委托定义了一个方法签名,该方法接受一个整数参数和一个字符串参数,并且没有返回值。委托是 C# 中一个非常强大的特性,它允许将方法作为参数进行传递,并在不同的上下文中调用这些方法。 阅读详情

相关推荐

C#中PredicateT与FuncT, bool泛型委托的用法实例

本文以实例形式分析了C#中Predicate<T>与Func<T>泛型委托的用法,分享给大家供大家参考之用。具体如下: 先来看看下面的例子: static void Main(string[] args) { List<string> l = new List<string>(); l.Add(a); l.Add(b); l.Add(s); l.Add(t); if (l.Exists(s => s.Equals(s))) { string str = l.First(s => s.Equals(s)); C

C# List<Func<T,bool>

C# List<Func<T,bool> 实现多条件选择器 以字符串为例 List<Func<string, bool>> selectors = new List<Func<string, bool>> { param=>param.StartsWith("AAA"),//条件1 param=>param.Contains("BBB"),//条

u013104793的博客 493

Electron多窗口开发避坑指南:Pinia状态同步的3种解决方案对比

本文深入探讨了在Electron多窗口应用中实现Pinia状态同步的三种核心方案。针对Electron多窗口架构下状态隔离的挑战,文章对比了基础事件通信、共享存储以及智能Pinia插件等方案的优劣与适用场景,并提供了生产级的实现指南与选型建议,帮助开发者构建健壮高效的桌面应用。

spice的博客 479

C#中的Predicate<T>与Func<T, bool>

C#有很多语法糖,有时使用时会觉得模棱两可, 以前很少用Predicate,因为英文太长,不如Func实在, 在我感觉中,这两个本该就是同一个东西。 但你会发现: (1)List类的所有方法如Exists, Find, FindAll, FindIndex等全是接受Predicate类型参数的 (2)而List类实现的接口IEnumerable的所有扩展方法如All,Any,Firs

rye_grass的专栏 1万+

飞牛NAS+Docker打造私人IPTV直播源:手把手教你部署iptv-api

本文详细介绍了如何在飞牛NAS上通过Docker部署iptv-api,打造私人IPTV直播源。从SSH配置到Docker容器部署,手把手教你实现自动更新直播源、多终端支持的解决方案,适用于Kodi、PotPlayer等播放器,提升家庭娱乐体验。

earth的博客 5560

【Boost5】Boost变换器的输入电容

节点的电流有3个,一个是来自电源输入的,由于我们把Vin看成理想电源以及线路的电感的存在,它可以近似看作是恒定的电流源Iin,一个是流向输入电容Cin的电流Icin,另外一个节点是电感L电流IL。电容电流波形在整个开关周期内的平均值为0,充电和放电在一个周期中各占1/2,在图中充电部分面积和放电部分面积相等,那么在充电或放电的电荷量Q=I*t,从图中可以看出,在一个周期内电容电流变化量是ΔIL,那在电容在充电1/2T周期中电流的变化量是1/2ΔIL。输入电容上的ESR也会随着电流变化,影响输入电压的变化。

qq_43416206的博客 3346

委托——Func委托

using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace Func委托 { class Program { // ****************************...

胤长風的博客 267

Modelsim10.5_se安装(Win11)

modelsim是Mentor公司开发的优秀的HDL语言仿真软件。它能提供友好的仿真环境,采用单内核支持VHDL和Verilog混合仿真的仿真器。它采用直接优化的编译技术、Tcl/Tk技术和单一内核仿真技术,编译仿真速度快且编译的代码与平台无关。

m0_51186267的博客 9907

动态拼接Expression<Func<T, bool>> lambda表达式

【代码】动态拼接Expression lambda表达式。

我是阿兰的博客 1070

S905L3B机顶盒刷Armbian:从安卓Root到eMMC全攻略

在嵌入式开发与轻量级服务器搭建中,ARM架构设备因其低功耗和高性价比备受关注。晶晨S905L3B作为运营商机顶盒的主流芯片,通过刷写Armbian系统可将其改造为ARM小服务器。其原理是利用Amlogic芯片的uboot引导机制,将Linux系统写入eMMC存储,从而脱离原厂安卓限制。这一方案的技术价值在于以极低成本实现Docker容器、下载机、轻量数据库等服务的部署,应用场景涵盖家庭网络广告过滤、智能家居控制、复古游戏机等。本文以CM311-1S为例,详细拆解从安卓9 Root到Armbian写入eMMC

weixin_31476015的博客 340

AI: 机器学习的模型是如何训练的?(在试错中学习)

一句话理解机器学习一般训练过程 :通过有标签样本来调整(学习)并确定所有权重Weights和偏差Bias的理想值。 训练的目标:最小化损失函数 (损失函数下面马上会介绍) 机器学习算法在训练过程中,做的就是:检查多个样本并尝试找出可最大限度地减少损失的模型;目标就是将损失(Loss)最小化 在这里插入图片描述 上图就是一般模型训练的一般过程(试错过程),其中 模型: 将一个或多个特征作为输入,然后返回一个预测 (y’) 作为输出。为了进行简化,不妨考虑一种采用一个特征并返回一个预测的模型,如下公式

HowieXue 薛永浩的博客 3万+

C#中委托

文章目录一、C#委托二、隐式类型与匿名类型三、C#扩展方法与yield关键字四、Lambda表达式 一、C#委托 举例1: 创建控制台应用程序 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace TheOne { //声明委托 public delegate string Translatio

weixin_46596213的博客 4435

Spring AI Alibaba 项目源码学习(九)-其他继承BaseAgent

本文分析了Spring AI Alibaba Agent Framework中的A2aRemoteAgent实现,主要特点包括: 实现了Agent间的远程调用能力,支持分布式部署 核心组件包括AgentCard封装元数据、A2aNodeActionWithConfig处理调用逻辑、AgentCardProvider提供卡片管理 支持流式调用和状态共享机制 采用Builder模式构建Agent实例 通过指令传递实现Agent间通信 关键流程包括状态提取、请求构建、远程调用和状态更新四个步骤,形成Agent

819

C#——委托

Action是.NET Framework内置的泛型委托,可以使用Action委托以参数形式传递方法,而不用显示声明自定义的委托。使用多播委托就可以按照顺序调用多个方法,多播委托只能得到调用的最后一个方法的结果,一般我们把多播委托的返回类型声明为void。引用可在运行时被改变。定义了一个委托叫做 IntMethodInvoker ,这个委托可以指向带有一个int类型的参数,并且返回值是void的一个方法。在定义好委托后就可以实例化委托,命名方法委托在实例化委托时必须带入方法的具体名称或者是null。

m0_51743362的博客 1万+

网络速度的极致:800G & 1.6T 以太网的突破!

你好,这里是网络技术联盟站。在我们进入数据驱动的世界时,以太网的重要性日益突出。从根本上说,以太网是一种连接计算机的技术,旨在形成一个本地网,通过它,设备可以与其他设备进行通信。然而,随着时间的推移,以太网已经发展成为一种全球的数据通信系统,其速度从初始的10Mbit/s发展到现在的800G,甚至1.6T。这种巨大的进步并不是没有挑战的,但每一次的突破都代表了技术的巨大飞跃。本文将探讨800G和1.6T以太网的创新与挑战。

网络技术联盟站 1769

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

c#————委托

定义:委托是一种引用类型,存储了对方法的引用,即委托的内部包含一个指向某个方法的指针。委托可以看作是方法的抽象,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递。声明:委托的声明类似于变量声明,需要指定委托类型和变量名。委托类型定义了方法的签名,包括返回类型和参数列表。例如,声明了一个名为MyDelegate的委托,它引用了一个返回void类型、带有一个string类型参数的方法。

2401_82978699的博客 1467

迈瑞BS系列全自动生化分析仪LIS协议接口手册(内含HL7和ASTM)

迈瑞BS系列全自动生化分析仪LIS协议接口手册,内含HL7和ASTM)

C# 委托和事件委托

C# 本文描述了什么是委托,什么是事件委托,如何他们,并使用C#代码描述了如何实现的。 目录: 什么是委托? 1、概念 2、代码描述委托 什么是事件委托? 1、概念 2、代码描述事件委托

C/C#、Android driver、STM32、Linux等等。 1987

OV9734 DATASHEET,完整规格书

OV9734完整规格书,包括电气参数,尺寸规格,寄存器配置表等

jre9下载 jdk9

(Java SE Runtime Environment 9.0) 9.0u175 官方最新版 【x86|x64】

C#中为啥要有委托,以及委托的使用。

通俗讲,所谓委托就是将函数作为变量去使用。 一个类似的动作一直在做。但是还有细微的差别,比如:中国人问好是:"你好,XXX",而美国人问好是:“Hello,XXX” 将问好这个动作封装为函数的话,就会出现如下两个函数,这两个函数应该这么写: public static void ChineseSayHi(string name){ Console.WriteLine("你好"...

qq_41877039的博客 3170

C# 委托详解

C# 委托出初理解

weixin_56939868的博客 1112

C#之委托

新添加的两个方法本质上没有区别都是对委托链的实现,不同的是写法,明显是第二个方法更加精简一些。第一次调用Counter,传递Null,在回调方法里有一步判空操作,所以是不回调用回调函数的。举个例子:我现在是一家公司的老板,公司现在在招聘.NET工程师,我们有一个小姐姐专门负责接受求职者投递的简历,我就告诉这个小姐姐,一旦收到新的简历就转发给我一份。=>左边是要传入的参数,本例中是传入一个Int类型的变量,=>右边是具体的代码,相当于FeedbackToConsole(),{}中所做的操作。...

m0_62355555的博客 740

【C#】委托是什么

在 C# 中,委托(Delegate)是一种类型安全的函数指针,可以将方法作为参数传递或者保存方法的引用。

qq_52208569的博客 1043

C#中的委托

开发工具与关键技术: MVC 撰写时间:2021/9/18 下面我们来讲C#中的委托和事件; 委托的概念: 委托从字面上理解就是一种代理,类似于房屋中介,由租房人委托中介为其租赁房屋。 在 C# 语言中,委托则委托某个方法来实现具体的功能。 委托的特点: (1) 委托是一种引用类型,在定义委托时与方法有些相似; (2) 从数据结构来讲,委托是和类一样是一种用户自定义类型; (3) 委托是方法的抽象,它存储的就是一系列具有相同签名和返回回类型的方法的地址; (4) 调用委托的时候,委托包含的所有方法将

无 3181

C#中委托的用法

前言 大家好,我是阿辉。 昨天大家和我一起学习了,C#中的委托,了解了什么是委托,也简单写了一个委托的完整实例。那么为什么会出现委托!委托该如何使用! 委托有如下好处: 委托实现了将方法当作参数使用。 在两个不能直接调用的方法中作为桥梁。比如在多线程中的跨线程的方法调用就得用委托。 当不知道方法具体实现什么时使用委托。如事件中使用委托。 委托的用法 给委托赋值 由于委托是引用类型,可通过给它赋值来改变包含在委托变量中的引用,旧的委托将被GC回收处理。 //给委托赋值 testOne

讲述工作、生活、技术中的日常与感悟。 4114
上一篇: C#使用委托进行异步编程
下一篇: Hide a file in a picture
捡石子的小孩
博客等级 码龄14年 51粉丝 117原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值