15.匿名函数

15.委托和事件-匿名函数


15.1 知识点

什么是匿名函数

匿名函数就是没有名字的函数。匿名函数的使用主要是配合委托和事件进行使用。脱离委托和事件是不会使用匿名函数的。

匿名函数的基本语法

匿名函数的基本语法如下:

delegate (参数列表)
{
    // 函数逻辑
};

匿名函数何时使用?

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

匿名函数的使用

class语句块外 namespace语句块内

// 测试类
class Test
{
    // 测试类内部的委托
    public Action action;

    // 存在委托作为参数的函数
    public void ExistDelegateParam(int a, Action fun)
    {
        Console.WriteLine(a);
        fun();
    }

    // 有委托作为返回值的函数
    public Action DelegateReturn()
    {
        // 学了匿名函数之后可以直接返回匿名函数
        return delegate ()
        {
            Console.WriteLine("函数内部返回的一个匿名函数");
        };
    }

    // 测试用到无参无返回的函数
    public void TestFun()
    {

    }
}

主函数内

无参无返回值的匿名函数:

// 这样申明匿名函数只是在申明函数而已,还没有调用
Action action1 = delegate ()
{
    Console.WriteLine("无参无返回值的匿名函数");
};

// 执行委托
action1(); // 无参无返回值的匿名函数

有参无返回值的匿名函数:

Action<int, string> action2 = delegate (int a, string b)
{
    Console.WriteLine("有参无返回值的匿名函数" + "int:" + a);
    Console.WriteLine("有参无返回值的匿名函数" + "string:" + b);
};

action2(100, "123");
// 有参无返回值的匿名函数int: 100
// 有参无返回值的匿名函数string: 123

有返回值的匿名函数:

Func<string> func1 = delegate ()
{
    return "有返回值的匿名函数";
};

Console.WriteLine(func1()); // 有返回值的匿名函数

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

// 创建测试类
Test test = new Test();

// 分两步传入匿名函数
Action action3 = delegate ()
{
    Console.WriteLine("随参数传入的匿名函数逻辑");
};
// 把action3作为参数传入测试类中存在委托作为参数的函数中
test.ExistDelegateParam(50, action3);
// 50
// 随参数传入的匿名函数逻辑

// 一步到位,直接传入匿名函数
// 把匿名函数作为参数传入测试类中存在委托作为参数的函数中
test.ExistDelegateParam(100, delegate ()
{
    Console.WriteLine("随参数传入的匿名函数逻辑");
});

// 分两步调用委托返回值函数
// 用action4装载委托返回值函数
Action action4 = test.DelegateReturn();
// 执行action4
action4(); // 函数内部返回的一个匿名函数

// 一步到位,直接调用返回的委托返回值函数
test.DelegateReturn()(); // 函数内部返回的一个匿名函数

匿名函数的缺点

// 添加到委托或事件容器中后,不记录,无法单独移除

Action action5 = delegate ()
{
    Console.WriteLine("匿名函数一");
};

action5 += delegate ()
{
    Console.WriteLine("匿名函数二");
};

action5();
// 匿名函数一
// 匿名函数二

// 因为匿名函数没有名字,所以没有办法指定移除某一个匿名函数
// 此匿名函数,非彼匿名函数,不能通过看逻辑是否一样就证明是一个
// action5 -= delegate ()
// {
//    Console.WriteLine("匿名函数一");
// };

// 不得已的话,只能清空,但是也会把不想删的东西也移除了
action5 = null;
// action5();//报错,委托为空

总结

匿名函数就是没有名字的函数,固定写法为:

delegate(参数列表){}

主要是在委托传递和存储时,为了方便可以直接使用匿名函数。缺点是没有办法指定移除。


15.2 知识点代码

using System;

namespace Lesson14_匿名函数
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("匿名函数");

            #region 知识点一 什么是匿名函数
            //顾名思义,就是没有名字的函数
            //匿名函数的使用主要是配合委托和事件进行使用
            //脱离委托和事件 是不会使用匿名函数的
            #endregion

            #region 知识点二 匿名函数的基本语法

            //匿名函数的基本语法
            //delegate (参数列表)
            //{
            //    //函数逻辑
            //};

            // 匿名函数何时使用?
            //1.函数中传递委托参数时
            //2.委托或事件赋值时

            #endregion

            //主函数内

            #region 知识点三 匿名函数的使用

            //1.无参无返回值的匿名函数
            //这样申明匿名函数 只是在申明函数而已 还没有调用
            //真正调用它的时候 是这个委托容器啥时候调用 就什么时候调用这个匿名函数
            Action action1 = delegate ()
            {
                Console.WriteLine("无参无返回值的匿名函数");
            };

            //记住 不能直接这样写出匿名函数 会报错
            //要给委托赋值时或传递委托参数时使用
            //delegate ()
            //{
            //    Console.WriteLine("无参无返回值的匿名函数");
            //};

            //执行委托
            action1();//无参无返回值的匿名函数



            //2.有参无返回值的匿名函数
            Action<int, string> action2 = delegate (int a, string b)
            {
                Console.WriteLine("有参无返回值的匿名函数" + "int:" + a);
                Console.WriteLine("有参无返回值的匿名函数" + "string:" + b);
            };

            action2(100, "123");
            //有参无返回值的匿名函数int: 100
            //有参无返回值的匿名函数string: 123


            //3.有返回值的匿名函数
            Func<string> func1 = delegate ()
            {
                return "有返回值的匿名函数";
            };

            Console.WriteLine(func1());//有返回值的匿名函数


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

            //创建测试类
            Test test = new Test();


            //分两步传入匿名函数
            //把匿名函数传入进action3
            Action action3 = delegate ()
            {
                Console.WriteLine("随参数传入的匿名函数逻辑");
            };
            //把action3  作为参数 传入测试类中存在委托作为参数的函数中
            test.ExistDelegateParam(50, action3);
            //50
            //随参数传入的匿名函数逻辑


            //一步到位 直接传入匿名函数
            //直接把
            //delegate ()
            //{
            //    Console.WriteLine("随参数传入的匿名函数逻辑");
            //};
            //作为参数 传入测试类中存在委托作为参数的函数中
            test.ExistDelegateParam(100, delegate ()
            {
                Console.WriteLine("随参数传入的匿名函数逻辑");
            });
            //100
            //随参数传入的匿名函数逻辑


            //分两步调用 委托返回值函数
            //用action4 装载 委托返回值函数
            Action action4 = test.DelegateReturn();
            //执行action4
            action4();//函数内部返回的一个匿名函数


            //一步到位 直接调用返回的 委托返回值函数
            test.DelegateReturn()();//函数内部返回的一个匿名函数

            #endregion

            #region 知识点四 匿名函数的缺点

            //添加到委托或事件容器中后 不记录 无法单独移除

            Action action5 = delegate ()
            {
                Console.WriteLine("匿名函数一");
            };

            action5 += delegate ()
            {
                Console.WriteLine("匿名函数二");
            };

            action5();
            //匿名函数一
            //匿名函数二

            //因为匿名函数没有名字 所以没有办法指定移除某一个匿名函数
            //此匿名函数 非彼匿名函数 不能通过看逻辑是否一样 就证明是一个 
            //action5 -= delegate ()
            //{
            //    Console.WriteLine("匿名函数一");
            //};

            //不得已的话 只能清空 但是也会把不想删的东西也移除了
            action5 = null;
            //action5();//报错 委托为空

            #endregion
        }
    }

    //class语句块外 namespace语句块内

    #region 知识点三 匿名函数的使用

    //测试类
    class Test
    {
        //测试类内部的委托
        public Action action;

        //存在委托作为参数的函数
        public void ExistDelegateParam(int a, Action fun)
        {
            Console.WriteLine(a);
            fun();
        }

        //有委托作为返回值的函数
        public Action DelegateReturn()
        {
            //return TestFun;
            //return action;
            //没学匿名函数之前的写法 一定要返回一个函数或者委托出去

            //学了匿名函数之后可以直接返回匿名函数
            return delegate ()
            {
                Console.WriteLine("函数内部返回的一个匿名函数");
            };
        }

        //测试用到无参无返回的函数
        public void TestFun()
        {

        }
    }

    #endregion


    //总结
    //匿名函数 就是没有名字的函数
    //固定写法 
    //delegate(参数列表){}
    //主要是在 委托传递和存储时  为了方便可以直接使用匿名该函数
    //缺点是 没有办法指定移除
}

15.3 练习题

写一个函数传入一个整数,返回一个函数(返回的是匿名函数),之后执行这个匿名函数时传入一个整数和之前那个函数传入的数相乘,返回结果

class语句块内 主函数外

// 写一个函数传入一个整数,返回一个函数(返回的是匿名函数)
// 之后执行这个匿名函数时 传入一个整数和之前那个函数传入的数相乘
// 返回结果
static Func<int, int> TestFun(int i)
{
    // 因为要返回一个函数 所以可以用匿名函数
    // 因为执行匿名函数时要传入一个整数 所以匿名函数只有一个int类型的参数
    // 因为匿名函数返回传入一个整数和之前那个函数传入的数相乘的值 所以返回值是int
    // 所以可以确定委托的类型是Func<int, int>

    // 本来这个i 假如在TestFun函数执行完只后就没用了
    // 但是现在i被匿名函数包裹
    // 这种写法会改变 i的生命周期 
    return delegate (int v)
    {
        // 返回两数相乘
        return i * v;
    };
}

主函数内

// 两步走
// 先传入参数拿到返回的委托
Func<int, int> fun = TestFun(2);
// 再传入参数执行返回的委托
Console.WriteLine(fun(3)); // 6

// 一步到位 直接传入参数拿到返回的委托再传入参数执行
Console.WriteLine(TestFun(2)(3)); // 6

15.4 练习题代码

using System;

namespace Lesson14_练习题
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("匿名函数练习题");

            //主函数内

            #region 练习题一

            //两步走
            //先传入参数拿到返回的委托
            Func<int, int> fun = TestFun(2);
            //再传入参数执行返回的委托
            Console.WriteLine(fun(3));//6

            //一步到位 直接传入参数拿到返回的委托再传入参数执行
            Console.WriteLine(TestFun(2)(3));//6

            #endregion
        }

        //class语句块内 主函数外

        #region 练习题一
        //写一个函数传入一个整数,返回一个函数(返回的是匿名函数)
        //之后执行这个匿名函数时 传入一个整数和之前那个函数传入的数相乘
        //返回结果

        //因为这个函数要传入一个整数 所以函数只有一个int类型的参数
        //因为要返回一个函数 所以返回类型是一个委托
        static Func<int, int> TestFun(int i)
        {
            //因为要返回一个函数 所以可以用匿名函数
            //因为执行匿名函数时要传入一个整数 所以匿名函数只有一个int类型的参数
            //因为匿名函数呀返回传入一个整数和之前那个函数传入的数相乘的值 所以返回值是int
            //所以可以确定委托的类型是Func<int, int>

            //本来这个i 假如在TestFun函数执行完只后就没用了
            //但是现在i被匿名函数包裹
            //这种写法会改变 i的生命周期 
            return delegate (int v)
            {
                //返回两数相乘
                return i * v;
            };
        }

        #endregion
    }
}


转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。可以在下面评论区评论,也可以邮件至 785293209@qq.com

×

喜欢就点赞,疼爱就打赏