zoukankan      html  css  js  c++  java
  • C#委托基础

      委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递。委托类型有:delegate、Action、Func、Predicate。事件是一种特殊的委托。

    1、委托的声明

    1.1、Delegate 是常用到的一种声明。

      至少0个参数,至多32个参数,可以无返回值,也可以指定返回值类型。例如,表示有两个参数,并返回int型。

    /// <summary>
    /// 两数相乘的委托
    /// </summary>
    public delegate ResultT MultiplyDelegate<T1,T2,ResultT>(T1 x, T2 y);
    class Program
    {
        private static MultiplyDelegate<int, int, int> multiplyDelegate;
        static void Main(string[] args)
        {
            multiplyDelegate += Multiply;//或者:multiplyDelegate=new MultiplyDelegate<int, int, int>(Multiply);
            Console.WriteLine(multiplyDelegate(10, 20));
        }
    
        private static int Multiply(int x,int y)
        {
            return x * y;
        }
    }

    1.2、Action 无返回值的泛型委托。

    • Action 表示无参,无返回值的委托
    • Action<int,string> 表示有传入参数int,string无返回值的委托
    • Action<int,string,bool> 表示有传入参数int,string,bool无返回值的委托
    • Action<int,int,int,int> 表示有传入4个int型参数,无返回值的委托

      Action至少0个参数,至多16个参数,无返回值。

    static void Main(string[] args)
    {
        InvokeAction( new Action<string>(ShowString),"字符串Action委托");
        InvokeAction(new Action<Double>(ShowDouble), 9.09);
        InvokeAction<string>(p=> { Console.WriteLine(p); }, "Lambda表达式委托");
    }
    
    private static void InvokeAction<T>(Action<T> action,T t)
    {
        action.Invoke(t);
    }
    
    private static void ShowString(string s)
    {
        Console.WriteLine(s);
    }
    
    private static void ShowDouble(double d)
    {
        Console.WriteLine(d);
    }

    1.3、Func 有返回值的泛型委托

    • Func<int> 表示无参,返回值为int的委托
    • Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
    • Func<object,string,int> 表示传入参数为object, string 返回值为int的委托
    • Func<T1,T2,,T3,int> 表示传入参数为T1,T2,,T3(泛型)返回值为int的委托

      Func至少0个参数,至多16个参数,根据返回值泛型返回。必须有返回值,不可是void。

     class Program
     {
         static void Main(string[] args)
         {
             Func<int, int, int> func = new Func<int, int, int>(Multiply);
             Console.WriteLine(func(10, 20));
         }
    
         private static int Multiply(int x,int y)
         {
             return x * y;
         }
     }

      可以使用 Action<T1, T2, T3, T4> 委托以参数形式传递方法,而不用显式声明自定义的委托。 封装的方法必须与此委托定义的方法签名相对应。 也就是说,封装的方法必须具有四个均通过值传递给它的参数,并且不能返回值。(在 C# 中,该方法必须返回 void)通常,这种方法用于执行某个操作。

    1.4、Predicate 返回bool型的泛型委托

      Predicate<int> 表示传入参数为int 返回bool的委托。Predicate有且只有一个参数,返回值固定为bool。该委托表示定义一组条件并确定指定对象是否符合这些条件的方法。此委托由 Array 和 List 类的几种方法使用,用于在集合中搜索元素。

    static void Main(string[] args)
    {
        Tuple<int, int> tuple1 = new Tuple<int, int>(89, 34);
        Tuple<int, int> tuple2 = new Tuple<int, int>(12, 34);
        Tuple<int, int> tuple3 = new Tuple<int, int>(125, 30);
        Tuple<int, int> tuple4= new Tuple<int, int>(192, 340);
        Tuple<int, int>[] tuples = new Tuple<int, int>[] { tuple1, tuple2, tuple3, tuple4 };
        Tuple<int, int> frist = Array.Find(tuples, Product);
        Console.WriteLine(frist.ToString());
    }
    
    private static bool Product(Tuple<int ,int> tuple)
    {
        return tuple.Item1> tuple.Item2;
    }

      使用带有 Array.Find 方法的 Predicate 委托搜索 Tuple<int ,int> 的数组。如果 Item1大于Item2,此委托表示的方法 Product将返回 true。Find 方法为数组的每个元素调用此委托,在符合测试条件的第一个点处停止。

    2、多播委托

      前面使用到的委托都只包含了一个方法的调用。调用委托的次数与调用方法的次数相同。如果要调用多个方法,需要多次显示调用该方法---多播委托。多播委托的签名必须返回void,否则只能获取到最后一个方法的结果。多播委托使用前面的“multiplyDelegate += Multiply”形式实现添加多个委托方法。如果正在使用多播委托,对同一委托调用方法链的顺序并未正式定义,因此应该避免编写依赖于以特定顺序调用方法的代码。

      多播委托可能出现调用方法停止问题。如果委托方法中的某一个方法抛出异常,整个迭代就会停止,未执行的方法便不会执行。定义两个方法One()与Two(),其中One()方法中会抛出一个异常

    private static void One()
    {
        Console.WriteLine("One");
        throw new Exception("One");
    }
    
    private static void Two()
    {
        Console.WriteLine("Two");
    }

      在Main()方法中创建一个委托d,引用One和Two方法。调用委托d,并使用try……catch捕获异常:

    static void Main(string[] args)
    {
        Action d = One;
        d += Two;
    
        try
        {
            d();
        }
        catch(Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

       解决多播委托的异常导致整个迭代方法停止问题,便需要有自己的迭代方法。使用Delegate类定义GetInvocationList()方法获取添加到委托的Delegate对象数组,使用循环迭代、捕获异常即可:

    static void Main(string[] args)
    {
        Action d = One;
        d += Two;
    
        Delegate[] delegates = d.GetInvocationList();
        foreach (Action item in delegates)
        {
            try
            {
                item();
            }
            catch (Exception e)
            {
                Console.WriteLine(e.Message);
            }
        }
    }

     3、委托的清空

      委托的添加可以像前面使用“+”符号添加,同样的可以使用“-”符号来减少委托。也可以对委托重新赋值为null,清空所有委托。

    4、委托的优点

    • 委托类似于 C++ 函数指针,但它们是类型安全的
    • 委托允许将方法作为参数进行传递
    • 委托可用于定义回调方法
    • 委托可以链接在一起;例如,可以对一个事件调用多个方法
    • 方法不必与委托签名完全匹配
    I travel alone,not to be alone.
  • 相关阅读:
    Java用户自定义函数
    JavaScript常用函数
    Javascript 流程控制
    Javascript基础
    CSS的继承和使用方式
    Python列表
    Python变量和简单数据类型
    CSS选择符
    CSS的基本语法
    Java环境变量搭建
  • 原文地址:https://www.cnblogs.com/pilgrim/p/9230921.html
Copyright © 2011-2022 走看看