委托、lambda表达式

301 阅读2分钟

一、委托类型和委托实例

1、委托类型

委托类型定义了委托实例可以调用的那类方法,具体来说,委托类型定义了方法的返回类型参数

delegate int Transformer(int x)

  • int 返回类型
  • Transformer 委托类型
  • (int x) 参数

2、委托实例

Transformer t = Square ;

  • t 委托实例

3、调用

int answer = t(3); //answer is 9

二、多播委托

一个委托实例可以引用一组目标方法

1、合并实例委托

+和+=操作符可以合并委托实例

SomeDelegate d = SomeMethod1;
d += SomeMethod2;

三、实例方法目标

当一个实例方法被赋值给委托对象的时候,这个委托对象不仅要保留着对方法的引用,还要保留着方法所属实例的引用。

class Program
    {
        delegate void ProgressReporter(int x);
        class X
        {
            public void InstanceProgress(int percentcomplete) => Console.WriteLine(percentcomplete);
        }

        static void Main(string[] args)
        {
            X x = new X();
            ProgressReporter p = x.InstanceProgress; 
            p(99);
            Console.WriteLine(p.Target == x); //True  方法所属实例
            Console.WriteLine(p.Method); //Void InstanceProgress(Int32)   方法
            Console.ReadLine();
        }
    }

四、泛型委托类型

委托类型可以包含泛型类型参数

public delegate T Transformer<T> (T arg);

  • 返回类型是T,参数也是T
    public delegate T Transformer<T>(T arg);

    public class Util
    {
        public static void Transform<T>(T[] values, Transformer<T> t)  //参数: 一个数组 , 一个委托类型

        {
            for (int i = 0; i < values.Length; i++)
            {
                values[i] = t(values[i]);
            }
        }
    }
    class Program
    {
        static void Main()
        {
            int[] values = { 1, 2, 3 };
            Util.Transform<int>(values, Square);   // Util.Transform(values, Square); 可以这样子简写,可以通过参数推断

            //经过调用Transform之后,values的值已经变了
            foreach (int i in values)
            {
                Console.Write(i + " ");
            }
            Console.ReadLine();
        }

        static int Square(int x) => x * x;

    }

五、Func 和 Action 委托

  • Action 无返回值
  • Func 有返回值
class Program
    {
        static void Main()
        {
            Action action1 = new Action(M1);
            action1();

            Action<string, int> action2 = new Action<string,int>(SayHello);
            action2("zhonglq",18);

            Func<int, int, int> func_add = new Func<int, int, int>(Add);
            Console.WriteLine(func_add(2, 3)); //5

            Func<double, double, double> func_mul = new Func<double, double, double>(Mul);
            Console.WriteLine(func_mul(2, 3));  //6

            Console.ReadKey();
        }

        static void M1()
        {
            Console.WriteLine("M1 is called");
        }

        static void SayHello(string name,int round)
        {
            Console.WriteLine(name + round);
        }

        static int Add(int x,int y)
        {
            return x + y;
        }

        static double Mul(double x,double y)
        {
            return x * y;
        }        
    }

六、lambda表达式

两个知识点的交集

  • 匿名方法
  • inline方法 (调用时才声明的方法)

逐渐简化的过程

 Func<int, int, int> f = new Func<int, int, int>((a, b) => { return a + b; });
 Console.WriteLine(f(5, 3));

 Func<int, int, int> f1 = (a, b) => { return a + b; }; //去掉了委托的new
 f1 = (x, y) => { return x * y; };

泛型方法+泛型的委托类型参数+泛型参数

class Program
    {
        static void Main()
        {
            DoSomeCalc<int>((int a, int b) => { return a * b; }, 100, 200);
            DoSomeCalc<int>((a,b) => { return a * b; }, 100, 200); //根据100 和200 可以推断 泛型委托的类型参数推断
            Console.ReadKey();
        }

        static void DoSomeCalc<T>(Func<T,T,T> func,T x,T y)
        {
            T res = func(x, y);
            Console.WriteLine(res);
        }
     

    }