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

15 篇文章 0 订阅
6 篇文章 0 订阅

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

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

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
    }
}

输出结果如下:

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

List<string> 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 子句和方法中直接分配。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值