由List.Find()引出闭包的概念



下面代码如果不使用Lambda表达式,自己写一个函数findobj,你会发现一个问题。

就是if (data.ToString() == "1") return true; 这句是写死的字符串,它应该是个变量。

但是为啥系统的List.Find定义的委托偏偏是下面这样的原型呢?

public delegate bool Predicate<in T>(T obj);


为啥不是下面这样呢?

public delegate bool Predicate<in T>(T obj, T obj2);



            System.Predicate<string> find = findobj;
            var list1 = new List<string>();
            list1.Add("1"); list1.Add("2");
            list1.Find(find);
            
             private bool findobj<T>(T data)
        {
            if (data.ToString() == "1") return true;
            return false;
        }



下面是使用匿名方法+Lambda表达式,你就发现外部变量可以传入进来了。

变量str是怎么做到传递到匿名函数里去的?

 var str = "2";

            findobjDelegate find= findobj;

            list1.Find(delegate(string s)

            {

                if (s == str) return true;

                return false;

            }

            );

        private bool findobj( string data)

        {

            if (data == "1") return true;

            return false;

        }



在这段代码中,str 变量被传递到匿名函数(即闭包)中,这个过程涉及到C#中的闭包和Lambda表达式。

首先,让我们来理解一下闭包。闭包是一个可以访问其外部作用域变量的函数。在C#中,匿名函数(即没有名字的函数)和Lambda表达式都可以被编译成闭包。

在这段代码中,list1.Find 方法接受一个委托(delegate),这个委托是一个匿名函数。这个匿名函数访问了外部作用域的 str 变量。

当 list1.Find 方法调用这个匿名函数时,它会将列表中的每个元素作为参数传递给这个函数。如果列表中的元素与 str 相等,那么匿名函数将返回 true,否则返回 false

这里的关键是 str 变量被闭包捕获并可以在匿名函数中被访问。即使 list1.Find 方法在匿名函数执行之后结束,str 变量仍然可以在匿名函数中被访问,因为闭包持有对 str 变量的引用。

总结一下,这段代码通过闭包机制将 str 变量传递到匿名函数中,使得匿名函数可以访问并使用 str 变量的值。


因此,对于List.Find方法来它,它那个委托,就是必须使用Lambda表达式来调用,你使用一个委托方法来调用就只能写死判断条件了。


这说明一个问题,.net类库中的一些委托调用,被设计成只能通过匿名函数或者Lambda表达式来调用。设计者也许是故意这样做,好利用闭包来简化调用参数。


勇哥的这个想法,在网上没人聊这个话题,于是问了下AI,
我让AI不使用匿名函数或者是Lambda表示式,写一个调用List.Find()的例子。
结果AI反复写都不对,它只能违规使用匿名函数或者Lambda表达式,才可以完成要求。

最后它这样回答:
image.png


AI说的第4点,下面是一个例子:

using System;  
using System.Collections.Generic;  
using System.Linq;  
  
class Program  
{  
    static void Main()  
    {  
        List<string> list = new List<string> { "apple", "banana", "orange", "grape" };  
  
        // 定义多播委托  
        Func<string, bool> multicastDelegate = (string element) =>  
        {  
            Console.WriteLine($"Element '{element}' found by the first delegate.");  
            return true;  
        };  
  
        // 添加多个委托到多播委托中  
        multicastDelegate += (string element) =>  
        {  
            Console.WriteLine($"Element '{element}' found by the second delegate.");  
            return true;  
        };  
  
        // 添加多个委托到多播委托中  
        multicastDelegate += (string element) =>  
        {  
            Console.WriteLine($"Element '{element}' found by the third delegate.");  
            return true;  
        };  
  
        // 执行多播委托逻辑  
        foreach (var element in list)  
        {  
            if (multicastDelegate(element))  
            {  
                Console.WriteLine("Element found.");  
            }  
        }  
    }  
}



--------------------- 

作者:hackpig

来源:www.skcircle.com

版权声明:本文为博主原创文章,转载请附上博文链接!

本文出自勇哥的网站《少有人走的路》wwww.skcircle.com,转载请注明出处!讨论可扫码加群:
本帖最后由 勇哥,很想停止 于 2023-12-15 16:23:51 编辑

发表评论:

◎欢迎参与讨论,请在这里发表您的看法、交流您的观点。

会员中心
搜索
«    2024年4月    »
1234567
891011121314
15161718192021
22232425262728
2930
网站分类
标签列表
最新留言
    热门文章 | 热评文章 | 随机文章
文章归档
友情链接
  • 订阅本站的 RSS 2.0 新闻聚合
  • 扫描加本站机器视觉QQ群,验证答案为:halcon勇哥的机器视觉
  • 点击查阅微信群二维码
  • 扫描加勇哥的非标自动化群,验证答案:C#/C++/VB勇哥的非标自动化群
  • 扫描加站长微信:站长微信:abc496103864
  • 扫描加站长QQ:
  • 扫描赞赏本站:
  • 留言板:

Powered By Z-BlogPHP 1.7.2

Copyright Your skcircle.com Rights Reserved.

鄂ICP备18008319号


站长QQ:496103864 微信:abc496103864