C# Delegates 委托

C# Delegates 委托

通常我们都是把数据作为参数传递给方法:int i = int.Parse(“99”);当需要把方法传送给其他方法时就需要使用委托。
类的用法,首先声明一个类,接着实例化一个类,委托的用法和类的用法类似,首先定义委托告诉编译器这种类型的委托表示哪种类型的方法,接着创建该委托的一个或者多个实例。

声明委托

委托的类型安全性非常高,在定义委托时必须给出他所表示的方法的签名和返回值,例如声明委托如下:
delegete void IntMethodInvoker(int x); 该方法带有一个int型参数,返回void。
假设需要定义一个委托,该委托表示的方法有两个long类型的参数,返回值为double:
delegete double TwoLongOp (long l1,long l2);

根据定义委托的可见性和委托的作用域,可以在委托的定义上应用任意常见的访问修饰符:public,private,protected。

使用委托

创建委托的实例:
IntMethodInvoker intMethod = null;
TwoLongOp twoLongOp = null;

namespace Delegates
{
    class Program
    {
    	// 声明委托
        private delegate string GetString();
        static void Main(string[] args)
        {
        	// 定义一个委托的实例getString
            GetString getString = null;
            int i = 99;
            // 给委托赋值
            getString = i.ToString; 
            Console.WriteLine($"{getString()}");
        }
    }
}

在给委托赋值时,这个方法必须匹配委托声明时的签名,在调用时使用了类似方法的getString(),C#编译器会用getString.Invoke()代替getString()。

Action< T >和Func< T >委托

泛型Action< T >委托表示引用一个void返回类型的方法。Action< T >可以调用8个参数的方法。
泛型Func< T >委托允许调用返回类型的方法。Fun< T >至多可以传递16个参数类型和一个返回类型,例如:Func<int T,out T>。

    class Program
    {
        private delegate double DoubleOp(double x);
        static void Main(string[] args)
        {
            DoubleOp[] operations = { MathOpertions.MuliplyByTwo,MathOpertions.Squate};
            for(int i = 0; i < operations.Length; i++)
            {
                ProcessAndDisplayNumble(operations[i], 2.0);
                ProcessAndDisplayNumble(operations[i], 7.94);
                ProcessAndDisplayNumble(operations[i], 1.414);
            }
            Console.WriteLine($"");
        }
        static void ProcessAndDisplayNumble(DoubleOp action, double value)
        {
            double result = action(value);
            Console.WriteLine($"value={value},operation result ={result}");
        }
    }
    class MathOpertions
    {
        public static double MuliplyByTwo(double value) => value * 2;
        public static double Squate(double value) => value * value;
    }

上面列举了一个普通的委托实例,需要先声明一个委托,下面用Fun< double T , double T >修改上面的代码,不需要声明委托。

        static void Main(string[] args)
        {
            Func<double,double>[] operations = { MathOpertions.MuliplyByTwo,MathOpertions.Squate};
            for(int i = 0; i < operations.Length; i++)
            {
                ProcessAndDisplayNumble(operations[i], 2.0);
                ProcessAndDisplayNumble(operations[i], 7.94);
                ProcessAndDisplayNumble(operations[i], 1.414);
            }
            Console.WriteLine($"");
        }
        static void ProcessAndDisplayNumble(Func<double, double> action, double value)
        {
            double result = action(value);
            Console.WriteLine($"value={value},{action.ToString()} result ={result}");
        }
    }
    class MathOpertions
    {
        public static double MuliplyByTwo(double value) => value * 2;
        public static double Squate(double value) => value * value;
    }

多播委托

以上每个委托都只包含一个方法调用,调用委托的次数和调用 方法的次数相同。委托可以包含多个方法,如果调用多播委托,就会按照顺序连续调用多播委托中的方法。多播委托可以识别‘+’、‘+=’、‘-’、‘-=’。

    class Program
    {
        static void Main(string[] args)
        {
            Action<double> operations = null;
            operations = MathOpertions.MuliplyByTwo;
            operations += MathOpertions.Square;
            double[] arr = new double[]{ 2.0, 7.94, 1.414 };
            foreach(var item in arr)
            {
                operations(item);
            }
            Console.WriteLine($"Hello World");
        }
    }
    class MathOpertions
    {
        public static void MuliplyByTwo(double value) 
        {
            double result = value * 2;
            Console.WriteLine($"MuliplyByTwo value={value} reult={result}");
        }
        public static void Square(double value) 
        {
            double result = value * 2;
            Console.WriteLine($"Square value={value} reult={result}");
        }
    }

多播委托顺序执行方法
使用多播委托会有一个问题:通过委托调用的其中一个方法抛出异常,整个迭代就会停止。如下代码所示,在方法中假装抛出异常:

    class Program
    {
        static void Main(string[] args)
        {
            Action<double> operations = null;
            operations = MathOpertions.MuliplyByTwo;
            operations += MathOpertions.Square;
            double[] arr = new double[]{ 2.0, 7.94, 1.414 };
            foreach(var item in arr)
            {
                operations(item);
            }
            Console.WriteLine($"Hello World");
        }
    }
    class MathOpertions
    {
        public static void MuliplyByTwo(double value) 
        {
            double result = value * 2;
            Console.WriteLine($"MuliplyByTwo value={value} reult={result}");
            throw new Exception("this is a Exception");
        }
        public static void Square(double value) 
        {
            double result = value * 2;
            Console.WriteLine($"Square value={value} reult={result}");
        }
    }

多播委托抛出异常终止迭代
解决这个问题:使用try…catch,抛出异常后循环继续

class Program
    {
        static void Main(string[] args)
        {
            Action<double> operations = null;
            operations = MathOpertions.MuliplyByTwo;
            operations += MathOpertions.Square;
            double[] arr = new double[]{ 2.0, 7.94, 1.414 };
            foreach(var item in arr)
            {
                try
                {
                    operations(item);
                }catch(Exception e)
                {
                    Console.WriteLine(e.Message);
                }
                
            }
            Console.WriteLine($"Hello World");
        }
    }
    class MathOpertions
    {
        public static void MuliplyByTwo(double value) 
        {
            double result = value * 2;
            Console.WriteLine($"MuliplyByTwo value={value} reult={result}");
            throw new Exception("this is a Exception");
        }
        public static void Square(double value) 
        {
            double result = value * 2;
            Console.WriteLine($"Square value={value} reult={result}");
        }
    }

多播委托抛出异常迭代继续
虽然循环继续,但是每次只执行第一个方法,因为第一个方法抛出异常后委托的迭代会停止。解决这个问题,需要自己迭代方法列表:

    class Program
    {
        static void Main(string[] args)
        {
            Action<double> operations = null;
            operations = MathOpertions.MuliplyByTwo;
            operations += MathOpertions.Square;
            Delegate[] delegates = operations.GetInvocationList();
            double[] arr = new double[]{ 2.0, 7.94, 1.414 };
            foreach(var item in arr)
            {
                foreach(Action<double> d in delegates)
                {
                    try
                    {
                        d(item);
                    }
                    catch (Exception e)
                    {
                        Console.WriteLine(e.Message);
                    }
                }   
            }
            Console.WriteLine($"Hello World");
        }
    }
    class MathOpertions
    {
        public static void MuliplyByTwo(double value) 
        {
            double result = value * 2;
            Console.WriteLine($"MuliplyByTwo value={value} reult={result}");
            throw new Exception("this is a Exception");
        }
        public static void Square(double value) 
        {
            double result = value * 2;
            Console.WriteLine($"Square value={value} reult={result}");
        }
    }

委托内方法迭代

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值