zoukankan      html  css  js  c++  java
  • part01.03 委托与 Lambda 表达式(二):匿名方法

    匿名方法

    在 2.0 之前的 C# 版本中,声明委托的唯一方法是使用命名方法。 C# 2.0 引入了匿名方法,而在 C# 3.0 及更高版本中,Lambda 表达式取代了匿名方法,作为编写内联代码的首选方式。 不过,本主题中有关匿名方法的信息同样也适用于 Lambda 表达式。 有一种情况下,匿名方法提供了 Lambda 表达式中所没有的功能。 就是可使用匿名方法来忽略参数列表。 这意味着匿名方法可转换为具有各种签名的委托。 这对于 Lambda 表达式来说是不可能的。

    匿名方法的简要说明:

    1.“匿名方法” 就是没有名称的方法,通常用于将代码块作为委托参数进行传递。

    2.匿名函数是一个 “内联(inline)” 语句或表达式,可在需要委托类型的任何地方使用。

    3.匿名函数可以使用匿名方法来初始化命名委托,或传递命名委托(而不是命名委托类型)作为方法参数。

    使用匿名方法处理委托和使用 Lambda 表达式处理委托实例:相关代码说明

     1  /// <summary>
     2     /// 定义一个委托方法(类型)
     3     /// </summary>
     4     /// <param name="i">int 变量</param>
     5     /// <param name="j">double 变量</param>
     6     delegate void DelegateMethod(int i, double j);
     7 
     8     /// <summary>
     9     /// 定义一个普通的类
    10     /// </summary>
    11     class SomeClass
    12     {
    13         /// <summary>
    14         /// 定义一个打印两个数字的方法
    15         /// </summary>
    16         /// <param name="m"></param>
    17         /// <param name="n"></param>
    18         public void PrintDigit(int m, double n)
    19         {
    20             Console.Write(m * n + " ");
    21         }
    22     }
    23 
    24     class Program
    25     {
    26         static void Main(string[] args)
    27         {
    28             #region 实例化委托的传统方式
    29             var a = new SomeClass();
    30 
    31             // 使用 SomeClass 的实例方法实例化委托
    32             var b = new DelegateMethod(a.PrintDigit);
    33             // 此时委托实例执行的是:a.PrintDigit
    34             b(1, 2.5);
    35             #endregion
    36 
    37             #region 使用匿名方法处理委托
    38             DelegateMethod c = delegate (int m, double n) 
    39             {
    40                 Console.Write(m + n + " ");
    41             };
    42             c(1, 2.5);
    43             #endregion
    44 
    45             #region 使用 Lambda 表达式处理委托实例化
    46             DelegateMethod d = (int m, double n) => { Console.Write(m - n + " "); };
    47             d(1, 2.5);
    48             #endregion
    49 
    50             Console.ReadKey();
    51         }
    52     }
    View Code

    Func<> 和 Action<> 简介

    public delegate TResult Func<in T, out TRsult>(T arg)

    1. 类型参数:

      In T : 此委托封装的方法的参数类型。该类型参数是可逆的,即可以使用指定的类型或派生程度更低的类型。

      out TRsult : 此委托封装的方法的返回值类型。该类型参数是协变的,即可以使用指定的类型或派生类更高的类型。

    2.参数 arg 类型

      T : 此委托封装的方法的参数。

    3.返回值类型

      Tresult : 此委托封装的方法的返回值

    可以使用此委托表示一种能以参数形式传递的方法,而不是显式声明自定义委托。封装的方法必须与此委托定义的方法签名相对应。也就是说,封装的方法必须具有一个通过值传递给它的参数,并且必须返回值。

    若要引用具有一个参数并返回 void 的方法,请改用 Action<T> 委托。

                //  带返回值的委托,实例化 Func<T1,T2,Tresult> 委托,不需要显式定义一个新委托并将命名方法分配给该委托
                Func<int, double, double> a = (m, n) => { return m * n; };
                Console.WriteLine(a);
                Console.WriteLine(a(10, 25.2));
    
                //  不带返回值的委托
                Action<int> b = x => { Console.WriteLine(x); };
                b(100);
               
                Console.ReadKey();                           

     要将代码块传递为委托参数,创建匿名方法则是唯一的方法。通过使用匿名方法,由于不必创建单独的方法,因此减少了实例化委托所需的编码系统开销。

    // 为点击事件创建一个处理程序。
    button1.Click += delegate(System.Object o, System.EventArgs e)
                       { System.Windows.Forms.MessageBox.Show("Click!"); };
    // 创建一个委托
    delegate void Del(int x);
    
    // 使用匿名方法实例化委托
    Del d = delegate(int k) { /* ... */ };

    例如,如果创建方法所需的系统开销是不必要的,则指定代码块(而不是委托)可能非常有用。 启动新线程即是一个很好的示例。 无需为委托创建更多方法,线程类即可创建一个线程并且包含该线程执行的代码。

    void StartThread()
    {
        System.Threading.Thread t1 = new System.Threading.Thread
          (delegate()
                {
                    System.Console.Write("Hello, ");
                    System.Console.WriteLine("World!");
                });
        t1.Start();
    }

    匿名方法的参数的范围是 “匿名方法块” 。

    如果局部变量和参数的范围包含匿名方法声明,则该局部变量和参数称为该匿名方法的 “外部” 变量。

    //    n 是一个外部变量
    int n = 0;
    Del d = delegate() { System.Console.WriteLine("Copy #:{0}", ++n); };

    外部变量的引用  被认为是捕获在创建委托时。 与本地变量不同,捕获的变量的生存期内扩展,直到引用该匿名方法委托被垃圾回收。

    匿名方法不能访问外部范围的 ref  或 out 参数。

    在 “匿名方法块” 中不能访问任何不安全代码。

    在 is 运算符的左侧不允许使用匿名方法。

    实例化委托的两种方法:

    • 使委托与匿名方法关联。

    • 使委托与命名方法 (DoWork) 关联。

    // 声明一个委托
        delegate void Printer(string s);
    
        class TestClass
        {
            static void Main()
            {
                // 使用匿名方法实例化委托类型
                Printer p = delegate (string j)
                {
                    System.Console.WriteLine(j);
                };
    
                // 匿名委托调用的结果
                p("调用使用匿名方法的委托");
    
                // 委托实例化使用命名方法“DoWork”
                p = new Printer(TestClass.DoWork);
    
                // 传统委托调用的结果
                p("调用使用命名方法的委托");
            }
    
            // 与命名委托关联的方法
            static void DoWork(string k)
            {
                System.Console.WriteLine(k);
            }
        }
        /* 输出:
             调用使用匿名方法的代理。
             调用使用命名方法的委托。
        */
  • 相关阅读:
    移动端调试Vconsole
    Vue-返回顶部
    Vue-封装loading
    Vue-水印封装
    Vue-封装scroll触底
    微信小程序-图片上传
    前端面试题(2)
    前端常见面试题
    服务端渲染(SSR)和客户端(CSR)渲染的区别
    什么是模块化?模块化开发的好处
  • 原文地址:https://www.cnblogs.com/huangzewei/p/7285210.html
Copyright © 2011-2022 走看看