网站首页 > 教程文章 正文
委托
当要把方法当成参数传给其他方法时,就用到了委托。我们很多时候都是将一般的数据作为参数传递,但将方法作为参数传递可能你会觉得很少出现,其实不然。比如线程这一块,我们要提供启动线程的方法,Thread的构造函数的一个参数就是定义了线程要调用的方法。再比如,事件这里,可视化图形界面开发中很多时候就是处理事件,触发事件时,我们需要知道执行哪一个方法,这时就把要处理事件的方法作为参数传递给委托。我们可以将委托看成是一个特殊类型的对象,或者将委托看成是为方法的签名和返回值类型指定了一个名称,这样就非常好理解了。
要使用委托,首先应该先声明一个委托,而你声明的这种类型的委托就表示可以接受哪种类型的方法,所以委托的类型安全性非常高,之后再创建这个委托的一个或多个实例。
delegate List<int> SelectData(List<int> allData, int num);
上面声明了一个委托,这个委托所指定所接受的方法带有一个List<int>类型的参数和一个int类型的参数,并且返回值类型为List<int>。
其实委托的定义特别像普通方法的定义,只是没有主体并用delegate修饰了。
委托的协变和逆变
协变可以理解为具体的输出,逆变可以理解为更加宽泛的输入。
public delegate object DelDemo(FileStream fs);
class Program
{
static void Main(string[] args)
{
// 可以指向
DelDemo del = MethodDemo;
}
public static string MethodDemo(Stream s)
{
return "hello";
}
}
上面代码中,输入变量为FileStream,输出为object,因为协变,可以返回一个具体的类型string,因为逆变,可以传入比较宽泛的Stream类型。
Action<T>和Func<T>委托
除了可以自己定义新的委托类型之外,还可以使用Action<T>和Func<T>委托。
Action<T>泛型委托表示可以引用返回值类型为void的方法,而传递的参数类型可以自己定义。没有参数的方法的话直接用非泛型版本Action即可。Action委托其实就是用来保存没有返回值的方法的一个委托,参数比较随便。
例如:需要保存一个有string类型参数无返回值的一个方法
Action<string> action1 = m => { Console.WriteLine(m) ; };
action("hello");
需要保存两个参数无返回值的一个方法
Action<int, int> action1 = (x, y) => { Console.WriteLine(x + y); };
action1(10, 20);
Func<T>委托只有泛型版本,Func委托其实就是用来保存一定有返回值的方法的一个委托,参数有没有无所谓。
例如:
//假设有一个M2方法
public int M2(int n1, int n2, int n3)
{
return n1 + n2 + n3;
}
// 前面三个是参数类型,最后一个是返回值类型
// 如果是Func<int>则表示没有参数,返回值类型是int的一个委托
Func<int, int, int, int> fun = M2;
fun(10, 20, 30);
多播委托
委托不仅只可以包含一个方法的调用,还可以包含多个方法,就是多播委托。调用多播委托,就按顺序连续调用多个方法,如果返回值类型不是void,就只能收到最后一个含有返回值委托的结果。
class Program
{
static void Main(string[] args)
{
Action action = M1;
action += M2;
action += M3;
action -= M2; // 减少方法,最后只输出m1 m3
action();
Console.ReadKey();
}
static void M1()
{
Console.WriteLine("m1");
}
static void M2()
{
Console.WriteLine("m2");
}
static void M3()
{
Console.WriteLine("m3");
}
}
如果某个方法出现异常,之后的方法都不会执行了。为了避免这个问题,可以自己迭代方法列表。通过Get InvocationList()返回一个Delegate对象数组,遍历这个数组时try-catch调用的方法,即使捕获了异常也可以继续下一次迭代。
- 上一篇: C#+web=?微软Blazor
- 下一篇: 9.C#关系运算符与逻辑运算符
猜你喜欢
- 2024-12-04 C#最常用的语法和方法(备用查询)
- 2024-12-04 C# 高级编程——委托
- 2024-12-04 运算符 - C#入门教程
- 2024-12-04 学习笔记之C#基础——变量与常量
- 2024-12-04 C# 入门深度学习:万字长文讲解微积分和梯度下降
- 2024-12-04 如何使用 C# 扩展方法
- 2024-12-04 9.C#关系运算符与逻辑运算符
- 2024-12-04 一个“txt文档”,就可以偷光你的秘密
- 2024-12-04 C#+web=?微软Blazor
- 2024-12-04 C#将窗口置于桌面下方实现动态桌面秀
- 最近发表
- 标签列表
-
- location.href (44)
- document.ready (36)
- git checkout -b (34)
- 跃点数 (35)
- 阿里云镜像地址 (33)
- qt qmessagebox (36)
- md5 sha1 (32)
- mybatis plus page (35)
- semaphore 使用详解 (32)
- update from 语句 (32)
- vue @scroll (38)
- 堆栈区别 (33)
- 在线子域名爆破 (32)
- 什么是容器 (33)
- sha1 md5 (33)
- navicat导出数据 (34)
- 阿里云acp考试 (33)
- 阿里云 nacos (34)
- redhat官网下载镜像 (36)
- srs服务器 (33)
- pico开发者 (33)
- https的端口号 (34)
- vscode更改主题 (35)
- 阿里云资源池 (34)
- os.path.join (33)