如何充分利用C#匿名方法的平台优势

news/2024/7/3 20:27:50
C# 1.1里,声明和使用委托要求你有委托和一个在委托被触发时具有匹配签名的能够执行的方法,以及一个将命名方法与委托关联的分配语句。作为C# 2.0的新特性,匿名方法基本上能够提供与先前命名方法相同的功能,但是它已经不再需要一个在关联到委托之前就明确创建的方法了。

你可以把匿名方法想象为一个实现与委托进行关联这项功能的便捷途径。如果同时看一下匿名方法实现和命名方法实现所取得IL结果,你会发现这两者之间的差别非常小。当编译器碰到匿名方法的时候,它会在类里面创建一个命名方法,并将它与委托进行关联。所以匿名方法在运行期间与命名方法的性能非常类似——性能的增加体现在开发人员的生产效率上,而不是运行期间的执行上。

如何使用匿名方法

多用代码少用说教来解释和理解匿名方法会容易一些。下面的例子应该能够说明你自己可以如何利用匿名方法的优势:

例1——基础知识

使用匿名方法很简单。你只需要把匿名方法放在你通常放命名方法的关联语句里。在下面这个例子里,我把匿名方法和示例1的委托关联在一起:

示例列表1

    #region Simple example - Example1
    privatedelegatevoidExample1();

    privatevoid btnExample1_Click(object sender, EventArgs e)
    {
        //Declare an instance of the Example1 delegate.
        // You can see where I'm using the anonymous
        // method in place of a named method - it follows
        // the delegate() keyword.
        Example1 example =
            newExample1(
                delegate()
                {
                    MessageBox.Show("Example1");
                });

        example();
    }
    #endregion

例2——变量范围

任何在匿名方法里声明的变量的范围都不会超出匿名方法的代码块。但是,匿名方法确实具有访问它们代码块之外的变量的能力,只要这些变量在匿名方法所使用的范围里。这些变量被微软称为外部变量。下面示2显示了匿名方法如何引用外部变量:

示例列表2

   #region Variable scope example - Example2
   privatedelegatevoidExample2();

   privatevoid btnExample2_Click(object sender, EventArgs e)
   {
       //Setup our parameters.
       string firstName = "Zach";
       string lastName = "Smith";

       //Create an instance of the Example2 delegate with an
       // anonymous method.
       Example2 example =
           newExample2(
               delegate() {
                   MessageBox.Show(firstName + " " + lastName);
              });

       //Execute the delegate.
       example();
   }
   #endregion

要注意的是,根据MSDN的文档,匿名方法里的refout参数无法被访问到。

 

例3——参数的传递

你可以将参数传递给匿名方法,方式就和你处理引用命名方法参数的委托一样。下面的示例3说明这种类型的功能:

示例列表3

   #region Parameter example - Example3
   privatedelegatevoidExample3(string firstName, string lastName);

   privatevoid btnExample3_Click(object sender, EventArgs e)
   {
       //Setup our parameters.
       string parameter1 = "Zach";
       string parameter2 = "Smith";

       //Create an instance of the Example3 delegate with an
       // anonymous method.
       Example3 example =
           newExample3(
               delegate(string firstName, string lastName)
               {
                   MessageBox.Show("Example3: " + firstName + " " + lastName);
               });

       //Execute the delegate.
       example(parameter1, parameter2);
   }
   #endregion

例4——多个方法的关联

就和命名方法一样,将多个匿名方法与同一个委托进行关联是可能的。这在很多情况下会非常有用——首先想到的是把一个简单的处理程序添加给按钮的点击事件。下面的代码(示例4)显示了一个委托,它同时带有与之相关联一个匿名方法和一个命名方法:

示例列表4

   #region Multiple method association (stacking) - Example4
   privatedelegatevoidExample4(string firstName, string lastName);

   privatevoid btnExample4_Click(object sender, EventArgs e)
   {
       //Setup our parameters.
       string parameter1 = "Zach";
       string parameter2 = "Smith";

       //Create an instance of the Example4 delegate with an
       // anonymous method.
       Example4 example =
           newExample4(
               delegate(string firstName, string lastName)
               {
                   MessageBox.Show("Example4: " + firstName + " " + lastName);
               });

       //Add another method to the delegate - this time
       // a named method.
       example += newExample4(Example4NamedMethod);

       //Execute the delegate.
       example(parameter1, parameter2);
   }

   privatevoid Example4NamedMethod(string firstName, string lastName)
   {
       MessageBox.Show("Example4Method: " + firstName + " " + lastName);
   }
   #endregion

例5——将匿名方法作为参数传递

就和命名方法一样,将匿名方法作为参数传递给函数是可能的。这并不是一个我认为会通常使用的特性,但是我敢肯定未来会有这种需要。下面的代码(5)说明了这种类型的功能,它将一个命名方法作为参数传递给了函数:

示例列表5

   #region Passing anonymous methods - Example5
   privatedelegatevoidExample5(string firstName, string lastName);

   privatevoid btnExample5_Click(object sender, EventArgs e)
   {
       //Execute Passit and pass the anonymous method.
       Passit((Example5)delegate(string firstName, string lastName)
               {
                   MessageBox.Show("Example5: " + firstName + " " + lastName);
               });

       //Execute Passit with the named method.
       Passit(Example5NamedMethod);
   }

   privatevoid Example5NamedMethod(string firstName, string lastName)
   {
       MessageBox.Show("Example5Method: " + firstName + " " + lastName);
   }

   privatevoid Passit(Example5 example)
   {
       example("Zach", "Smith");
   }
   #endregion

例6—-访问类成员

这是对上面2的变量范围的扩展。但是,这个例子(6)说明了匿名参数还能够在它们的代码块之外执行命名方法:

示例列表6

    #region Accessing class members - Example6
    privatedelegatevoidExample6();

    privateint _customerId;
    privatestring _customerCode;

    publicint CustomerID
    {
        get { return _customerId; }
        set { _customerId = value; }
    }

    publicstring CustomerCode
    {
        get { return _customerCode; }
        set { _customerCode = value; }
    }

    privatevoid btnExample6_Click(object sender, EventArgs e)
    {
        //Populate out properties.
        this.CustomerID = 90;
        this.CustomerCode = "1337HK";

        //Setup the delegate/anonymous method.
        Example6 example =
            newExample6(
                delegate
                {
                    this.ShowCustomer(this.CustomerID, this.CustomerCode);
                });

        //Execute the delegate.
        example();

        //Change the properties.
        this.CustomerID = 54;
        this.CustomerCode = "L4M3";

        //Execute the delegate again.
        // Notice that the new values are reflected.
        example();
    }

    privatevoid ShowCustomer(int customerId, string customerCode)
    {
        MessageBox.Show(
            String.Format("CustomerID: {0}nCustomer Code: {1}",
                            customerId, customerCode));
    }
    #endregion

要注意的是,我两次调用了与匿名方法相关联的委托。你可能会发现一个很有趣的事情:在这些调用中,方法会输出两组不同的值。这是因为用在匿名方法里的外部变量在创建匿名方法的时候被引用。这意味着对这些变量的任何更改都会在匿名函数访问变量的时候被反映出来。

你可能还注意到在这个实例里委托关键字后面没有括号。当匿名方法不需要带参数的时候,后面的括号是可选的。

评论

我希望本文已经说明如何使用匿名方法。虽然它们还不是革命性的,但是它们是C#演化成为一门程序员友好的语言过程中的一个重要步骤。

 


http://www.niftyadmin.cn/n/3711230.html

相关文章

【转】论函数调用约定

假设我们有这样的一个函数: int function(int a,int b) 调用时只要用result function(1,2)这样的方式就可以使用这个函数。但是,当高级语言被编译成计算机可以识别的机器码时,有一个问题就凸现出来:在CPU中,计算 机…

Microsoft C 和 C++ 编译器与链接器

CL.exe 是控制 Microsoft C 和 C 编译器与链接器的 32 位工具。编译器产生通用对象文件格式 (COFF) 对象 (.obj) 文件。链接器产生可执行文件 (.exe) 或动态链接库文件 (DLL)。 注意,所有编译器选项都区分大小写。 若要编译但不链…

Open CV系列学习笔记(六)模糊操作 2021-01-31

Open CV系列学习笔记(六)模糊操作 什么是模糊操作? 模糊操作的作用是在图片时减低噪声。 模糊操作有均值模糊,中值模糊,高斯模糊和自定义模糊 模糊操作的基本原理: 1、基于离散卷积 2、定义好每一个卷积核…

转贴C/C++用移位实现乘除法运算,提高运行效率

用移位实现乘除法运算 aa*4; bb/4; 可以改为&#xff1a; aa<<2; bb>>2; 说明&#xff1a; 除2 右移1位 乘2 左移1位 除4 右移2位 乘4 左移2位 除8 右移3位 乘8 左移3位 ... ... 通常如果需要乘以或除以2的n次方&#xff0c;都可以用移位的方法代替。 大部分…

Open CV系列学习笔记(七)边缘保留滤波(EPF) 2021-02-01

Open CV系列学习笔记&#xff08;七&#xff09;边缘保留滤波(EPF) 高斯双边 双边滤波&#xff08;Bilateral filter&#xff09;是一种非线性的滤波方法&#xff0c;是结合图像的空间邻近度和像素值相似度的一种折中处理&#xff0c;同时考虑空域信息和灰度相似性&#xff0c…

c++位运算,|,~,^,,

关键字&#xff1a;c位运算 什么是位(bit)&#xff1f; 很简单&#xff0c;位(bit)就是单个的0或1&#xff0c;位是我们在计算机上所作一切的基础。计算机上的所有数据都是用位来存储的。一个字节(BYTE)由八个位组成&#xff0c;一个字(WORD)是二个字节或十六位&#xff0c;一…

Open CV系列学习笔记(八)图像直方图 2021-02-02

Open CV系列学习笔记&#xff08;八&#xff09;图像直方图 什么是图像直方图 图像直方图由于其计算代价较小&#xff0c;且具有图像平移、旋转、缩放不变性等众多优点&#xff0c;广泛地应用于图像处理的各个领域&#xff0c;特别是灰度图像的阈值分割、基于颜色的图像检索以…

关于PInvoke 和COM Interop

关于PInvoke 和COM Interop.1. 平台调用利用平台调用这种服务&#xff0c;托管代码可以调用在动态链接库 (DLL)&#xff08;如 Win32 API 中的 DLL&#xff09;中实现的非托管函数。此服务将查找并调用导出的函数&#xff0c;然后根据需要跨越互用边界封送其参数&#xff08;整…