编程语言中高级特性:委托
形象的理解什么是委托
顾名思义,委托,把事情托付给他人或机构(办理)。诸如:“当事人委托律师出庭辩护”,“我能委托你办一件事吗”。总的来说就是委托方将具体的事情交给被委托方来做, 委托方不关心具体过程,只关心开始和结果。被委托方执行具体内容即可。
委托的使用会经历如下的过程
- 委托的声明: 定义委托内容中需要什么,达到什么样的效果。定义出庭辩护
- 编写委托方法: 按照定义的标准, 详细制定委托内容。出庭辩护的内容
- 实例化委托: 创建委托实例。某个律师有出庭辩护的资格
- 调用委托: 被委托人执行委托内容。这个律师执行辩护, 并将结果返回给当事人
委托可以将方法封装为其它方法的参数
委托(Delegate)特别用于实现事件
和回调方法
。所有的委托(Delegate)都派生自 System.Delegate 类。
委托的使用
声明委托
前面我们知道委托都是派生自System.Delegate 类, 所以委托是个类哦~
// 和接口方法声明一样, 只不过多了个delegate关键字, 注意没有方法体
public delegate int ShowDelegate(int a, int b);
另外, c#自带了两种委托, 如果你在程序中使用, 那么可以省略声明步骤
Action<参数1,... 参数N> // 无返回值的委托
Func<参数1,... 参数N> // 有返回值的委托(必须有返回值)
当然, 委托的类型可以是泛型, 表示泛型委托
, 泛型委托极大的提高了代码的扩展性。
编写委托方法
按照委托声明编写委托方法, 同普通方法一样即可
public static int AddNum(int a, int b)
{
// 方法内容
}
实例化委托
// 方式一: 通过new 委托 来实例化
ShowDelegate sd = new ShowDelegate(AddNum)
// 方式二: 使用赋值的方式
ShowDelegate sd = AddNum
// 方式三: 匿名委托, 这种方式 委托方法写在匿名委托中
ShowDelegate sd = delegate(int s, int v){
Console.WriteLine($"匿名委托,{s}&{v}");
}
// 方式四: 使用Lambda, 这种方式 委托方法写在Lambda中
ShowDelegate sd = (int s, int v) => { Console.WriteLine($"Lambda,{s}&{v}"); };
调用委托
// 方式一: 同步调用
sd(1, 2)
// 方式二: 同步调用
sd.Invoke(1, 2);
// 方式三: 异步调用
IAsyncResult iar = sd.BeginInvoke(3,4,null,null); // 异步调用
int result = sd.EndInvoke(iar); // 获取异步执行结果
完整代码
using System;
// 1.声明委托
delegate int ShowDelegate(int a, int b);
namespace DelegateAppl
{
class TestDelegate
{
static int num = 10;
// 2.编写委托方法
public static int AddNum(int m, int n)
{
num += m;
num += n;
return num;
}
public static int AddNum1(int m, int n)
{
num += m;
num += n;
return num;
}
public static int getNum()
{
return num;
}
static void Main(string[] args)
{
// 3.创建委托实例
ShowDelegate nc1 = new ShowDelegate(AddNum);
nc1 += AddNum1; // 委托的多播, 这里的nc1绑定了两个委托
ShowDelegate nc2 = new ShowDelegate(AddNum1);
// 4.使用委托对象调用方法
nc1(1, 2);
Console.WriteLine("Value of Num: {0}", getNum());
nc2(3, 4);
Console.WriteLine("Value of Num: {0}", getNum());
Console.ReadKey();
}
}
}
Action、Func、Predicate委托
// Action、Func、Predicate委托
// 无参数无返回值
// lambda实现委托实例
Action a1 = () => Console.WriteLine(1);
a1();
// delegate实现委托实例,下面不再演示delegate。
Action a2 = delegate { Console.WriteLine(1); };
a2();
// 有参数无返回值
Action<int> a3 = (x) => Console.WriteLine(x);
a3(1);
// 无参数有返回值的情况
Func<int> e1= ()=> 1;
var value1= e1();
// 有参数有返回值的情况
// 最后一个泛型是返回值的类型
Func<int,int> e2 = (x) => x+1;
int value2= e2(1);
// 多参数情况
Func<int, int,int> e3 = (x,x2) => x+x2 + 1;
int value3 = e3(1,2);
// 返回值是布尔类型
// 其实Predicate可以用Func返回值是bool来代替的。
Predicate<int> p = (x) => x > 0;
bool value4 = p(1);
委托的多播
可以理解成, 当事人既委托律师去打官司, 又委托同一个律师去保释
// 可以使用 变量 += 委托 或 变量 -= 委托 进行添加和删除委托
委托与函数指针
委托是从函数指针中发展而来, 但不像函数指针那样直接记录某函数的"门牌号码"和解析规则以供间接调用函数;而是以面向对象的方式定义一个类,这个类描述的是符合某种特征的方法,而这个类的对象可以作为参数被其它方法调用;委托当然也可以被直接调用。(因为委托的实例封装着方法,委托实例就是一种特殊的方法)
C#中的委托与函数指针在某些方面是有相似之处的,但也存在一些本质上的区别。
相似之处:
-
引用函数:委托和函数指针都可以用来引用函数。委托在C#中是一种类型,可以将方法引用存储在委托对象中,而函数指针在C#中可以通过使用unsafe关键字和delegate*指针类型来实现。
-
调用函数:委托和函数指针都可以用于调用函数。通过委托的Invoke()方法或者直接使用函数指针的调用语法,可以调用被引用的函数。
不同之处:
-
类型安全性:C#的委托是类型安全的,编译器会在编译时进行类型检查,确保委托的签名与引用的方法匹配。而函数指针在C#中需要使用unsafe关键字,并且不会进行类型检查,因此可能存在潜在的类型不匹配问题。
-
语法和语义:委托使用delegate关键字声明,并且可以使用多播委托来引用多个方法。而函数指针在C#中需要使用unsafe关键字声明,并且不能直接引用多个函数。
-
托管环境:委托是.NET框架的一部分,受到托管环境的管理和限制。而函数指针是在C#中使用unsafe代码块来实现的,并且不受托管环境的控制。
总结:
委托是C#中的一种类型,用于引用和调用方法,具有类型安全性、多播功能等特点。函数指针是在C#中使用unsafe关键字声明的指针类型,可以用于引用和调用函数,但需要注意类型安全性和托管环境的影响。委托是更常用、更推荐的一种机制,而函数指针在特定的场景下使用。
委托与回调函数
委托和回调函数在C#中常常一起使用,但它们是不同的概念和机制。
委托(Delegate)是一种类型,用于存储对方法的引用。通过定义委托类型,可以声明委托对象,并将其关联到特定的方法。委托允许您将方法作为参数传递,并在需要时调用该方法。它提供了一种实现回调机制的方式。可以将委托视为一个函数指针,它允许您以类型安全的方式引用和调用方法。
回调函数(Callback Function)是一种机制,其中函数可以作为参数传递给其他函数,并在需要时被调用。回调函数常用于异步操作或事件处理中。在C#中,回调函数通常通过委托来实现。通过将回调函数作为委托类型的参数传递给某个方法,当需要的时候,可以调用委托来执行回调函数。
委托和回调函数的关系如下:
- 委托可以用于存储对回调函数的引用。通过声明一个委托类型,可以创建委托对象,并将其关联到特定的方法,这个方法就是回调函数。
- 当需要执行回调操作时,可以通过调用委托对象来触发回调函数的执行。
通过委托和回调函数的组合,可以实现解耦和灵活性。委托允许您在运行时动态选择要执行的方法,而回调函数提供了一种向其他代码传递函数的能力。这种组合可以用于处理异步操作、事件处理、插件系统等各种场景
。
无论是C#中的委托还是JavaScript中的函数赋值给变量,都可以通过调用变量来执行相应的函数。这种方式可以方便地将函数作为值进行传递、存储和调用。委托和JavaScript中的函数都允许将函数作为一等公民对待,使得函数可以像其他数据类型一样进行操作。
扩展阅读
最后更新于 2023-07-24 16:59:12 并被添加「」标签,已有 477 位童鞋阅读过。
本站使用「署名 4.0 国际」创作共享协议,可自由转载、引用,但需署名作者且注明文章出处
此处评论已关闭