CS4L14——匿名函数

匿名函数

顾名思义,就是没有名字的函数,它主要用于传递一段简单且不会直接调用(主要通过委托调用)的逻辑
匿名函数的使用主要是配合委托和事件进行使用,直接将函数逻辑传递出去,而不用额外声明一个函数
脱离委托和事件 是不会使用匿名函数的(脱离委托事件也无法调用匿名函数,因为没有函数名让我们调用)

关于匿名函数的简便写法以及闭包等,详见:CS4L15——Lambda表达式

基本语法

1
2
3
4
delegate (参数列表)
{
//函数逻辑
}

何时使用?

  1. 函数中传递委托参数时
  2. 委托或事件赋值时

匿名函数的声明和使用

注意:使用 delegate​ 关键字定义的匿名函数最后要加 “;​” !!!
匿名函数必须要被一个委托或事件存储,或者作为参数传递,单独声明匿名函数是会报错的

真正调用匿名函数的时候,是在存储这个匿名函数的委托被调用的时候
有返回值的匿名函数不需要在 delegate​ 前加变量类型,直接在 Func​ 里或者接收逻辑的委托中指明返回值类型即可

  1. 无参无返回值

    1
    2
    3
    4
    5
    6
    7
    8
    Action a = delegate()
    {
    //这里相当于直接把一个没名字的函数直接存储到委托a里
    //这样申明 匿名函数只是在申明函数而已 还没有调用
    Console.WriteLine("匿名函数逻辑");
    };
    //真正调用匿名函数的时候 是在存储这个匿名函数的委托被调用的时候
    a();

    输出:

    1
    匿名函数逻辑
  2. 有参

    1
    2
    3
    4
    5
    6
    Action<int, string> b = delegate(int a, string b)
    {
    Console.WriteLine(a);
    Console.WriteLine(b);
    };
    b(100, "123");

    输出:

    1
    2
    100
    123
  3. 有返回值

    1
    2
    3
    4
    5
    6
    Func<string> c = delegate()
    {
    //不需要在delegate前加变量类型,直接在Func里指明返回值类型即可
    return "123123";
    };
    Console.WriteLine(c());

    输出:

    1
    123123

匿名函数一般情况会作为函数参数传递 或者 作为函数返回值

  • 参数传递

    没有匿名函数时必须要先申明一个函数才能作为参数,学习匿名函数后可以立刻申明一个匿名函数作为参数

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    class Test
    {
    //作为参数传递时
    public void DoSomething(int a, Action fun)
    {
    Console.WriteLine(a);
    fun();
    }
    }

    internal class Program
    {
    static void Main(string[] args)
    {
    //一般情况会作为函数参数传递 或者 作为函数返回值
    Test t = new Test();
    t.DoSomething(100, delegate()
    {
    Console.WriteLine("随参数传入的匿名函数");
    });
    //也可以分步骤
    Action ac = delegate()
    {
    Console.WriteLine("随参数传入的匿名函数");
    };
    t.DoSomething(100, ac);
    }
    }

    输出:

    1
    2
    3
    4
    100
    随参数传入的匿名函数
    100
    随参数传入的匿名函数
  • 函数返回值

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    class Test
    {
    //作为返回值
    public Action GetFun()
    {
    return delegate()
    {
    Console.WriteLine("函数内部返回的一个匿名函数逻辑");
    };
    }
    }

    internal class Program
    {
    static void Main(string[] args)
    {
    //一般情况会作为函数参数传递 或者 作为函数返回值
    Test t = new Test();
    // 返回值
    Action ac2 = t.GetFun();
    ac2();
    //可以一步到位,直接调用返回的委托函数
    t.GetFun()();
    }
    }

    输出:

    1
    2
    函数内部返回的一个匿名函数逻辑
    函数内部返回的一个匿名函数逻辑

匿名函数的缺点

匿名函数由于没有名字,因此添加到委托或者事件容器后,如果不记录这个匿名函数,匿名函数是无法单独移除

1
2
3
4
5
6
7
8
9
10
Action ac3 = delegate ()
{
Console.WriteLine("匿名函数一");
};
ac3 += delegate ()
{
Console.WriteLine("匿名函数二");
};

ac3();

这种情况下,因为匿名函数没有名字,无法再单独移除委托内某一个特定的匿名函数!!!
即使重新再声明一个匿名函数,它也不是上一个匿名函数(哪怕逻辑完全相同),
不可能通过看逻辑是否一样就证明这是同一个!因此 -=​ 匿名函数没有意义

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Action ac3 = delegate ()
{
Console.WriteLine("匿名函数一");
};
ac3 += delegate ()
{
Console.WriteLine("匿名函数二");
};

ac3();
//注意这种情况下,因为匿名函数没有名字,无法再单独移除委托内某一个特定的匿名函数!!!
//此匿名函数 非彼上一个匿名函数,不可能通过看逻辑是否一样就证明这是同一个!因此下面的语法没有意义
//ac3 -= delegate ()
//{
// Console.WriteLine("匿名函数一");
//};

一旦要移除匿名函数,就只能全部清空

1
ac3 = null;

因此,只要委托有移除其中的指定函数的需要,该委托就不建议使用匿名函数