委托定义类型,类型指定特定方法签名。 可将满足此签名的方法(静态或实例)分配给该类型的变量,然后(使用适当参数)直接调用该方法,或将其作为参数本身传递给另一方法再进行调用。 以下示例演示了委托的用法。

using System;
using System.Linq; public class Program
{
public delegate string Reverse(string s); static string ReverseString(string s)
{
return new string(s.Reverse().ToArray());
} static void Main(string[] args)
{
Reverse rev = ReverseString; Console.WriteLine(rev("a string"));
}
}
  • public delegate string Reverse(string s); 行创建特定签名的委托类型,在本例中即接受字符串参数并返回字符串参数的方法。
  • static string ReverseString(string s) 方法与定义的委托类型具有完全相同的签名,用于实现委托。
  • Reverse rev = ReverseString; 行显示可将方法分配给相应委托类型的变量。
  • Console.WriteLine(rev("a string")); 行演示如何使用委托类型的变量来调用委托。

为简化开发过程,.NET 包含一组委托类型,程序员可重用这些类型而无需创建新类型。 其中包括 Func<>Action<> 和 Predicate<>,可用于 .NET API 的各个位置,无需定义新委托类型。 当然,从这三者的签名可以看出它们之间存在某些差异,主要影响其既定用途:

  • Action<> 用于需要使用委托参数执行操作的情况。
  • Func<> 通常用于现有转换的情况,也就是说需要将委托参数转换为其他结果时。 最好的示例就是投影。
  • Predicate<> 用于需要确定参数是否满足委托条件的情况。 也可将其写作 Func<T, bool>

现在可使用 Func<> 委托而非自定义类型重新编写上述示例。 程序将照旧继续运行。

using System;
using System.Linq; public class Program
{
static string ReverseString(string s)
{
return new string(s.Reverse().ToArray());
} static void Main(string[] args)
{
Func<string, string> rev = ReverseString; Console.WriteLine(rev("a string"));
}
}

对于此简单示例而言,在 Main 方法之外定义方法似乎有些多余。 因此 .NET Framework 2.0 引入了匿名委托的概念。 在其支持下,可创建“内联”委托,而无需指定任何其他类型或方法。 只需在所需位置内联委托的定义即可。

例如,要进行切换并使用匿名委托筛选出只有偶数的列表,然后将其打印到控制台。

using System;
using System.Collections.Generic; public class Program
{
public static void Main(string[] args)
{
List<int> list = new List<int>(); for (int i = ; i <= ; i++)
{
list.Add(i);
} List<int> result = list.FindAll(
delegate (int no)
{
return (no % == );
}
); foreach (var item in result)
{
Console.WriteLine(item);
}
}
}

如你所见,该委托的正文只是一组表达式,其他所有委托也是如此。 但它并非单独定义,而是在调用List<T>.FindAll 方法时临时引入。

但是,即使使用此方法,仍有许多可以丢弃的代码。 此时就需要使用 lambda 表达式。

lambda 表达式(或简称“lambda”)在 C# 3.0 中作为语言集成查询的 (LINQ) 核心构建基块被首次引入。 这种表达式只是使用委托的更方便的语法。 它们将声明签名和方法正文,但在分配到委托之前没有自己的正式标识。 与委托不同,可将其作为事件注册的左侧内容或在各种 LINQ 子句和方法中直接分配。

由于 lambda 表达式只是指定委托的另一种方式,因此应可重新编写上述示例,令其使用 lambda 表达式而不是匿名委托。

using System;
using System.Collections.Generic; public class Program
{
public static void Main(string[] args)
{
List<int> list = new List<int>(); for (int i = ; i <= ; i++)
{
list.Add(i);
} List<int> result = list.FindAll(i => i % == ); foreach (var item in result)
{
Console.WriteLine(item);
}
}
}

在前面的示例中,所使用的 Lambda 表达式为 i => i % 2 == 0。 再次强调,它只是使用委托的一种非常方便的语法,因此其实际行为与使用匿名委托时相同。

再次强调,lambda 只是委托,这意味着可将其顺利用作事件处理程序,如以下代码片段所示。

public MainWindow()
{
InitializeComponent(); Loaded += (o, e) =>
{
this.Title = "Loaded";
};
}

此上下文中的 += 运算符用于订阅事件。

基础知识---委托和 lambda的更多相关文章

  1. C# 基础知识系列- 6 Lambda表达式和Linq简单介绍

    前言 C#的lambda和Linq可以说是一大亮点,C#的Lambda无处不在,Linq在数据查询上也有着举足轻重的地位. 那么什么是Linq呢,Linq是 Language Intergrated ...

  2. 《Java基础知识》Java Lambda表达式

    接触Lambda表达式的时候,第一感觉就是,这个是啥?我居然看不懂,于是开始寻找资料,必须弄懂它. 先来看一个案例: @FunctionalInterface public interface MyL ...

  3. C#基础知识之事件和委托

    本文中,我将通过两个范例由浅入深地讲述什么是委托.为什么要使用委托.委托的调用方式.事件的由来..Net Framework中的委托和事件.委托和事件对Observer设计模式的意义,对它们的中间代码 ...

  4. C#基础知识---Lambda表达式

    一.Lambda表达式简介 Lambda表达式可以理解为匿名函数,可以包含表达式和语句.它提供了一种便利的形式来创建委托. Lambda表达式使用这个运算符--- "=>", ...

  5. [C# 基础知识系列]专题一:深入解析委托——C#中为什么要引入委托

    转自http://www.cnblogs.com/zhili/archive/2012/10/22/Delegate.html 引言: 对于一些刚接触C# 不久的朋友可能会对C#中一些基本特性理解的不 ...

  6. C#基础加强篇—委托、Lambda表达式和事件(下)

    3.事件 事件作为C#中的一种类型,为类和类的实例定义发出通知的能力,从而将事件和可执行代码捆绑在了一起.事件是对象发送的消息,以发信号通知操作的发生.操作可能是由用户交互引起的,也可能是由某些其他的 ...

  7. JAVA基础知识|lambda与stream

    lambda与stream是java8中比较重要两个新特性,lambda表达式采用一种简洁的语法定义代码块,允许我们将行为传递到函数中.之前我们想将行为传递到函数中,仅有的选择是使用匿名内部类,现在我 ...

  8. 巩固基础知识,从C# in depth开始

    真是书到用时方恨少,平时都是完成任务,书都是看个前面几章就扔书柜了.... 今天看了博客园一篇文章<我们为什么应该坚持写博客>,很有感触,觉得人生不能得过且过,以前为了各种原因,家庭,孩子 ...

  9. [C# 基础知识系列]专题九: 深入理解泛型可变性

    引言: 在C# 2.0中泛型并不支持可变性的(可变性指的就是协变性和逆变性),我们知道在面向对象的继承中就具有可变性,当方法声明返回类型为Stream,我们可以在实现中返回一个FileStream的类 ...

随机推荐

  1. 洛谷 p1541乌龟棋

    洛谷 p1541乌龟棋 题目背景 小明过生日的时候,爸爸送给他一副乌龟棋当作礼物. 题目描述 乌龟棋的棋盘是一行NN个格子,每个格子上一个分数(非负整数).棋盘第1格是唯一的起点,第NN格是终点,游戏 ...

  2. 【转】Linux上安装rz和sz命令

    简介 lrzsz 官网入口:http://freecode.com/projects/lrzsz/ lrzsz是一个unix通信套件提供的X,Y,和ZModem文件传输协议 windows 需要向ce ...

  3. 针对JCC指令练习的堆栈图

    堆栈图,主要目的就是练习一下JCC指令的熟练度,供参考 版权声明:本文为博主原创文章,转载请附上原文出处链接和本声明.2019-09-10,23:41:41.作者By-----溺心与沉浮----博客园 ...

  4. PL/SQL Developer报错 ORA-12154:tns:could not resolve the connect identifier specified

    PL/SQL Developer使用预先配置数据库报错 ORA-12154:tns:could not resolve the connect identifier specified. 情况描述:我 ...

  5. Echarts 柱状图组

    通过Echarts可以实现柱状图组,如下图:是一个学生三次模考成绩对比结果 源码 <!DOCTYPE html> <html> <head> <meta ch ...

  6. 【分布式搜索引擎】Elasticsearch之如何安装Elasticsearch

    在Macos上安装 一.下载安装过程 最新版本下载地址: https://www.elastic.co/cn/downloads/elasticsearch 历史版本下载地址: https://www ...

  7. 操作Excel模块openpyxl

    安装 pip install openpyxl 想要在文件中插入图片文件,需要安装pillow font(字体类):字号.字体颜色.下划线等 fill(填充类):颜色等 border(边框类):设置单 ...

  8. 201871010112-梁丽珍《面向对象程序设计(java)》第十五周学习总结

    博文正文开头格式:(2分) 项目 内容 这个作业属于哪个课程 https://www.cnblogs.com/nwnu-daizh/ 这个作业的要求在哪里 https://www.cnblogs.co ...

  9. JWT 学习资料

    学习资料 网址 官方网站 https://jwt.io/ debugger https://jwt.io/#debugger 相关的类库 https://jwt.io/#libraries (java ...

  10. python基础语法20 面向对象5 exec内置函数的补充,元类,属性查找顺序

    exec内置函数的补充 exec: 是一个python内置函数,可以将字符串的代码添加到名称空间中; - 全局名称空间 - 局部名称空间 exec(字符串形式的代码, 全局名称空间, 局部名称空间) ...