C# Lambda及Predicate追根朔源-从一行代码说起

引子:

今天看一个文档,看到一行代码竟然没看懂,不得不承认知识结构老化了,然后由这行代码开始了探索之旅。这一行代码是:

var items = svgImageBox1.FindItems(item => item.Id != null && item.Id.StartsWith("background_pressed"));
items.ForEach(item => item.Visible = false);

正题:

关于 Predicate<>

我打算以我了解它过程的视角以倒序的方式展开,把这一行代码的来龙去脉说清楚。

svgImageBox1 为DevExpress 中一个装载SVG图形(矢量图形)的一个容器控件实例,不必纠结于控件本身,详细看链接(https://docs.devexpress.com/WindowsForms/DevExpress.XtraEditors.SvgImageBox?utm_source=visualstudio&utm_medium=DXHelpAssistant&utm_campaign=onlinehelp

第一条语句变形1:

图一

这里FindItems定义是:

图二

我们使用了匿名委托方式作为参数传递给FindItems,再看Predicate的定义:

图三

它也是一个委托,只不过必须要返回bool类型,并支持一个泛型参数,之所以能用图二方式传参数,是因为这个匿名委托的参数与返回值和Predicate的完全一致。

第一条语句变形2

图四

此处使用了非匿名委托方式,也就是专门定义了一个函数,再把这个函数与定义的委托变量my,也就是这个my成为了有执行能力的函数,它指向了我们定义的函数FindItem();相当于C++中的指针函数。

第一条语句变形3

图五

回到Predicate的定义,它的本质是一个特定返回值和参数的委托,委托的本质是一个函数引用,也就是只告诉编译器这里要调用一个有如此返回值,如此参数的函数,但函数本身的实现要重新实现才行。既然是这样,就不用定义一个显式的委托,把这个满足条件的函数名写进去,就相当于简化了过程。

第一条语句变形4

图六

这里对 my这个委托对象使用new的方式和FindItem()函数实现绑定。但我对

            Predicate<DevExpress.XtraEditors.SvgImageItem> my = FindItem;
            Predicate<DevExpress.XtraEditors.SvgImageItem> my = new Predicate<DevExpress.XtraEditors.SvgImageItem>(FindItem);

这两种方式有什么区别不太明白,感觉好像是new 产生了一个新对象,在内存中有独立的空间,委托的本质不就是一个函数指针,new 出来一个委托对象就是根据设计图纸重新做了一把钥匙(my)。直接等于相当于把原来的钥匙直接给了 (my),即my对象就是FindItem函数的入口地址。但思来想去还是有点迷胡,请高人指点一下。

小结一下:

var items = svgImageBox1.FindItems(item => item.Id != null && item.Id.StartsWith("background_pressed"));

语句中的item => item.Id != null && item.Id.StartsWith("background_pressed")

实际上就是匿名委托的lamdba表达式如下图所示:

item => item.Id != null && item.Id.StartsWith("background_pressed")

关于Func<> Action<>

这里不再展开详细描述,因为这位高手已经总结的很详细,直接粘贴上去,要看原文请访问:https://www.jb51.net/article/201334.htm

C#中的Action、Func和Predicate如何使用
更新时间:2020年12月03日 16:52:06 作者:码农读书
这篇文章主要给大家介绍了关于C#中Action、Func和Predicate如何使用的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
前言
委托是一个类型安全的函数指针,它可以引用与委托具有相同签名的方法。委托常用于实现回调方法或者事件机制,在C#中一般用 "delegate" 关键字声明。你可以声明一个和类平级的委托,也可以嵌套在类中。
Func 和 Action 是什么,如何使用?
两者最基本的区别是,前者适合那些需要带返回值的委托,后者适合那些不带返回值的委托。
Func 所引用的方法接收一个或者多个入参并带有一个返回值,Action所引用的方法接收一个或者多个参数并且没有返回值,换句话说,你的委托所引用的方法没有返回值,这时候适合用 Action。
Predicate所引用的方法接收一个或者多个泛型参数并且返回一个 bool 值,你可以假定它等价于 Func<T,bool>,Predicate 常用于对 collection 进行一组条件检索。
C# 中使用 Action
你可以使用 委托 去实现事件和回调方法,C#委托非常类似于C++中的函数指针,但是 C# 中的 委托 是类型安全的,你可以将方法作为参数传递给委托从而让委托指向该方法。
下面的代码片段展示了 Action 委托的语法结构。
static void Main(string[] args)
{
Action<string> action = new Action<string>(Display);
action("Hello!!!");
Console.Read();
}

static void Display(string message)
{
Console.WriteLine(message);
}

接下来的代码清单展示了如何使用 Action 委托,当下面的代码执行结束后会在控制台打印 Hello !!!。

C# 中使用 Func
现在我们一起学习下 Func 委托,下面是 Func 的语法结构。
static void Main(string[] args)
{
Func<int, double> func = new Func<int, double>(CalculateHra);
Console.WriteLine(func(50000));
Console.Read();
}
static double CalculateHra(int basic)
{
return (double)(basic * .4);
}

接下来的代码片段展示了如何在 C# 中使用 Func 委托,最终方法会打印出 Hra(基本薪资的 40%) 的值,基本薪资是作为参数传下去的,如下代码所示:
Func<TParameter, TOutput>
值得注意的是,Func 委托的第二个参数表示方法的返回值,在上面这个例子中,它就是计算后的 Hra 值,作为 double 型返回。
C# 中使用 Predicate
Predicate 委托常用于检索 collection,下面是 Predicate 的语法结构。

值得注意的是, Predicate<T> 差不多等价于 Func<T,bool>。
考虑下面的 Customer 实体类。

接下来生成一个 customer 集合并且丢一些数据进去,如下代码:

接下来是完整的代码片段展示了如何使用 Predicate 去检索集合。

当上面的代码被成功执行, 控制台将会输出 Joydip 。
译文链接:https://www.infoworld.com/article/3057152/how-to-work-with-action-func-and-predicate-delegates-in-csharp.html?nsdr=true
总结
到此这篇关于C#中Action、Func和Predicate如何使用的文章就介绍到这了,更多相关C#中Action、 Func和Predicate使用内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值