C# 匿名方法

在C#1.1里,声明和使用委托要求你有委托和一个在委托被触发时具有匹配签名的能够执行的方法,以及一个将命名方法与委托关联的分配语句。

namespace 匿名方法示例
{
    /// <summary>
    ///  C# 1.X中委托使用方法
    /// </summary>
    class Program
    {
        // 1. 声明 委托Sample
        delegate int Sample(int x, int y);

        // 2. 声明 与委托Sample 签名匹配的 方法Plus
        static int Plus(int x, int y)
        {
            return x + y;
        }

        static void Main(string[] args)
        {
            // 3. 将委托Sample 与 方法Plus 进行关联
            Sample f =new Sample(Plus);

            int result = f(1, 2);
            Console.WriteLine(result);
        }
    }
}

在C#2.0里,引入了匿名方法这个新特性,它允许开发者内联(inline)声明自己的函数代码而无须使用委托函数(delegate function)。匿名方法基本省能够提供与先前命名方法相同的功能,但是它已经不在需要一个在关联到委托之前就明确创建的方法了。当编译器遇到匿名方法时,编译器会在类里面创建一个命名方法,并将这个命名方法与委托进行关联。匿名方法的实现和命名方法的实现所取得的IL结果两者之间差别非常小,性能相差也非常小。

namespace 匿名方法示例
{
    /// <summary>
    ///  C# 2.0中匿名方法使用方法
    /// </summary>
    class Program
    {
        // 1. 声明 委托Sample
        delegate int Sample(int x, int y);

        static void Main(string[] args)
        {
            // 2. 使用匿名方法 
            Sample anonymousFunction = delegate(int x, int y) { return x + y; };

            int result = anonymousFunction(1, 2);
            Console.WriteLine(result);
        }
    }
}

匿名方法中的参数:

1.匿名方法可以接受实参,但什么都不做:

namespace 匿名方法示例
{
    /// <summary>
    ///  C# 2.0中匿名方法使用方法
    /// </summary>
    class Program
    {
        // 1. 声明 委托Sample
        delegate int Sample(int x, int y);

        static void Main(string[] args)
        {
            // 2. 使用匿名方法 ,匿名方法接受实参,但什么都不做
            Sample anonymousFunction = delegate(int x, int y) { return int.MaxValue; };

            int result = anonymousFunction(1, 2);
            Console.WriteLine(result);
        }
    }
}

2. 匿名方法忽略参数,虽然其对应的Delegate的定义是含有参数的:

namespace 匿名方法示例
{
    /// <summary>
    ///  C# 2.0中匿名方法使用方法
    /// </summary>
    class Program
    {
        // 1. 声明 委托Sample
        delegate int Sample(int x, int y);

        static void Main(string[] args)
        {
            // 2. 使用匿名方法 , 匿名方法忽略参数,虽然其对应的委托Sample的定义是含有参数的
            Sample anonymousFunction = delegate { return int.MaxValue; };

            int result = anonymousFunction(1, 2);
            Console.WriteLine(result);
        }
    }
}

注意:关于匿名方法的参数使用,只能以上两种情况二选一,要么忽略所有参数(参数个数为0与忽略参数是不同的,要区别对待),要么参数形式同其委托参数形式一致,否则编译器将会报错。

例如以下情况,编译器都会报错:

namespace 匿名方法示例
{
    /// <summary>
    ///  C# 2.0中匿名方法使用方法
    /// </summary>
    class Program
    {
        // 1. 声明 委托Sample
        delegate int Sample(int x, int y);

        static void Main(string[] args)
        {
            // 2. 使用匿名方法 , 匿名方法参数,要么忽略所有参数,要么参数形式同其委托参数形式一致,否则编译器将会报错
            Sample anonymousFunction = delegate() { return int.MaxValue; };
            Sample anonymousFunction1 = delegate(int x) { return int.MaxValue; };

            int result = anonymousFunction(1, 2);
            Console.WriteLine(result);
        }
    }
}

另外,匿名方法也可以声明泛型参数<T>,一个带泛型参数的匿名方法可以赋给一个同类型的delegate实例,只需确保其符合delegate签名即可

namespace 匿名方法示例
{
    /// <summary>
    ///  C# 2.0中匿名方法使用方法
    /// </summary>
    class Program
    {
        static void Main(string[] args)
        {
            TestClass<string> c = new TestClass<string>();
            c.Test("123");
        }
    }
    /// <summary>
    ///  匿名方法与泛型
    /// </summary>
    class TestClass<T>
    {
        // 1. 声明 委托Sample
        delegate void Sample(T t);
        public void Test(T t)
        {
            // 2. 使用匿名方法 , 匿名方法也可以声明泛型参数<T>,一个带泛型参数的匿名方法可以赋给一个同类型的delegate实例,只需确保其符合delegate签名即可
            Sample anonymousFunction = delegate(T arg) { Console.WriteLine(arg.ToString()); };
            anonymousFunction(t);
        }
    }
}

匿名方法的返回值:

1.如果委托类型的返回值类型为void,匿名方法里不能返回任何值,上面的委托与范型的例子中即返回值为void。

2.如果委托类型的返回值类型不为void,匿名方法的返回值也不能为void,即与委托类型返回值一致即可,上面的例子中返回值为int。

匿名方法的外部变量:

匿名方法有时会使用一些局部变量和参数,这些局部变量和参数被称为“匿名方法的外部变量”。外部变量的生存期会由于“匿名方法的捕获效益”而延长,直到委托实例不被引用为止。

namespace 匿名方法示例
{
    /// <summary>
    ///  C# 2.0中匿名方法使用方法
    /// </summary>
    class Program
    {
        // 1. 声明 委托Sample
        delegate void Sample();

        static void Main(string[] args)
        {
            int test = 100;
            // 2. 使用匿名方法 , 匿名方法外部参数的使用
            Sample anonymousFunction = delegate {
                Console.WriteLine(test);
                test = 200;
                Console.WriteLine(test);
            };
            Console.WriteLine(test);
            Console.WriteLine("Before Invoke:" + test);
            anonymousFunction.Invoke();
            Console.WriteLine("After Invoke:" + test);
            Console.WriteLine(test);

            Console.ReadKey();
        }
    }
}

程序输出:

100
Before Invoke:100
100
200
After Invoke:200
200

namespace 匿名方法示例
{
    /// <summary>
    ///  C# 2.0中匿名方法使用方法
    /// </summary>
    class Program
    {
        // 1. 声明 委托Sample
        delegate void Sample();

        static void Function(int test)
        {
            // 2. 使用匿名方法 , 匿名方法外部参数的使用
            Sample anonymousFunction = delegate
            {
                Console.WriteLine(test);
                test = 200;
                Console.WriteLine(test);
            };
            Console.WriteLine("Before Invoke:" + test);
            anonymousFunction.Invoke();
            Console.WriteLine("After Invoke:" + test);
        }

        static void Main(string[] args)
        {
            int test = 100;

            Console.WriteLine(test);
            Function(test);
            Console.WriteLine(test);

            Console.ReadKey();
        }
    }
}

程序输出:

100
Before Invoke:100
100
200
After Invoke:200
100

匿名方法对于外部变量的使用和正常的局部变量使用的方式没有太大的区别。

何时使用匿名方法:

1. 需要一个临时方法,该方法使用次数极少;

2. 这个方法的代码很短,甚至可能比方法声明都短;

注意:

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

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

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

在C#3.0中,引入了一个新的特性---Lambda表达式,它提供了完成相同目标的更加简介的格式。但有一种情况,匿名方法提供了 Lambda 表达式中所没有的功能。 可使用匿名方法来忽略参数列表。 这意味着匿名方法可转换为具有各种签名的委托。 这对于 Lambda 表达式来说是不可能的。

namespace 匿名方法示例
{
    /// <summary>
    ///  C# 3.0中Lambda表达式使用方法
    /// </summary>
    class Program
    {
        // 1. 声明 委托Sample
        delegate int Sample(int x, int y);

        static void Main(string[] args)
        {
            // 2. 使用Lambda表达式
            Sample plusDelegate = (x, y) => { return x + y; };

            int result = plusDelegate(1, 2);
            Console.WriteLine(result);
        }
    }
}

参考文章:

http://www.cnblogs.com/PolarLights/archive/2006/03/03/342416.html

http://www.cnblogs.com/kid-li/archive/2006/12/12/589455.html

原文地址:https://www.cnblogs.com/xixia/p/3988694.html