C#匿名函数之委托、Func、Action、Predicate、Lambda

    在写代码的过程中,并不是任何时候都会把一个代码块放在一个命名函数中,而且有可能的情况是:函数太多或者已有相似名称的函数,已经不知道要怎么去命名为好;又或者给中间函数命名后意义不大,基本不会复用......所以匿名函数不失为一种合适的选择。

    匿名函数的实现有多种方式(委托、匿名方法),另外需要注意的是尽管使用匿名函数尽管可以让代码变得简洁,但是要对匿名函数的正确使用引起充分的重视。如下代码:

using System;

delegate void D();

class Test
{
    static D[] F1()
        {
            D[] result = new D[3];
            int x;//注意区别
            for (int i = 0; i < 3; i++)
            {
                x = i * 2 + 1;
                result[i] = () => { Console.WriteLine("F1 result="+x.ToString()); };
            }
            return result;
        }
        static D[] F2()
        {
            D[] result = new D[3];
            for (int i = 0; i < 3; i++)
            {
                int x = i * 2 + 1;//注意区别
                result[i] = () => { Console.WriteLine("F2 result=" + x.ToString()); };
            }
            return result;
        }
        static D[] F3()
        {
            D[] result = new D[3];
            for (int i = 0; i < 3; i++)
            {
                //注意区别
                result[i] = () => { Console.WriteLine("F3 result=" + i.ToString()); };
            }
            return result;
        }

    static void Main() {
        foreach (D d in F1()) d();//5 5 5
        foreach (D d in F2()) d();//1 3 5 ,这个才是想要的输出
        foreach (D d in F3()) d();//3 3 3
    }
}

输出结果如下:

C#匿名函数之委托、Func、Action、Predicate、Lambda_第1张图片

    为何F1、F3没有按意料中类似F2地输出?原因参见微软文档中在“表达式”一节对匿名函数的描述:表达式

    个人关于C#的一些语法及基础演练源码,Git地址为:CSharpBasicCodePractice,如果对您有一定帮助,还望不吝点个Star,谢谢!

1.委托

    是一种引用类型,本质是方法指针。介绍:委托

    个人较常用的场景,在创建线程时:

Thread t0 = new Thread(new ThreadStart(delegate { Console.WriteLine("delegate"); }));
t0.Name = "t0";
t0.Start();

2.Func、Action、Predicate

    都是委托的一种表示方式(即.Net的内设委托),本质上都是委托。

①区别在于:

Func有可选参数,有返回类型;

Action有可选参数,无返回;

Predicate有参数(默认一个,多个参数需要较复杂的实现),固定返回bool类型;(多用于对数组和集合的查询操作中作为参数,如数组的Find函数)

②使用场景:

这三个函数中Action会使用的较多,比在WPF的线程调度器中对UI进行修改:

this.Dispatcher.BeginInvoke((Action)(() =>
{
    Console.WriteLine("this is lambda");
}));

Predicate的用法,简单举例如下:

List lists = new List() { "T0", "T1" };
Predicate isT0 = new Predicate(IsT0);//true如果obj满足此委托; 所表示的方法中定义的条件否则为false。
List T0 = lists.FindAll(isT0);

List T0_lambda = lists.FindAll(ss =>ss == "T0";);//lambda表达式写法

private static bool IsT0(string ss)
{
    return ss == "T0";
}

③更多的示例用法

    可以查看本人的git库中的“MultiThreadDemo”块,地址:C#基础及语法演练

3.lambda

    它并非C#语言独有的特性,它是委托的一种形式,内部原理与匿名委托类似,参考:委托和 lambda

其中一个例子认为很有用,将lambda表达式作为事件处理程序,如下:

public MainWindow()
{
    InitializeComponent();

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

4.小结

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

    为简化开发过程,.NET 包含一组委托类型,程序员可重用这些类型而无需创建新类型。 这些类型是 Func<>Action<> 和 Predicate<>,可以使用它们而无需定义新的委托类型。

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

你可能感兴趣的:(C#,多线程,开发进阶,c#,匿名函数,委托,lambda,方法封装)