C#委托(2)

笔记来自于《.NET4.0面向对象编程漫谈 基础篇》

Tag:多路委托,泛型委托,Func系列委托、Action系列委托与MethodInvoker、Predicate<T>委托

委托调用列表

委托变量可以组合多个方法并批量执行它们

组合方法:使用加法、减法运算符

Delegate类定义了一个GetInvocationList静态方法用于获取委托调用列表,通过这个函数可以了解委托的方法集

一个多路委托变量可以引用多个方法,执行一个多路委托变量,会导致它所包含的所有方法被顺序执行。

委托变量的内容是“只读”的,合并或分割委托列表得到的只是一个新的委托调用列表。

泛型委托:

.NET2.0开始,委托开始支持泛型技术,即泛型委托

一个简单的泛型委托例子:

        public delegate T MyGenericDelegate<T>(T obj1,T obj2);
        static int MyFunc(int val1,int val2)
        {
            return val1*val2;
        }
        void MainFormLoad(object sender,EventArgs e)
        {
            MyGenericDelegate<int> del;
            del=MyFunc;
            label1.Text=del(12,22).ToString();
        }
可以看到,泛型委托的使用与普通委托类似,不同之处在于使用泛型委托时需要指定泛型参数。

Func系列委托:
Func系列委托的定义:
        public delegate TResult Func<TResult>();
        public delegate TResult Func<T,TResult>(T arg);
        public delegate TResult Func<T1,T2,TResult>(T1 arg1,T2 arg2);
        public delegate TResult Func<T1,T2,T3,TResult>(T1 arg1,T2 arg2,T3 arg3);
        public delegate TResult Func<T1,T2,T3,T4,TResult>(T1 arg1,T2 arg2,T3 arg3,T4 arg4);

Func委托声明的最后一个泛型类型参数是委托所接收方法的返回值类型,前面的泛型参数就是委托所接收方法的形参类型
Func系列委托的例子:
        public delegate TResult Func<TResult>();
        public delegate TResult Func<T,TResult>(T arg);
        public delegate TResult Func<T1,T2,TResult>(T1 arg1,T2 arg2);
        public delegate TResult Func<T1,T2,T3,TResult>(T1 arg1,T2 arg2,T3 arg3);
        public delegate TResult Func<T1,T2,T3,T4,TResult>(T1 arg1,T2 arg2,T3 arg3,T4 arg4);
        static int Add(int i,int j){return i+j;}
        static int Multiply(int i,int j){return i*j;}
        static int Process(Func<int,int,int> op,int[] numbers,int from,int to)
        {
            int result=numbers[from];
            for(int i=from;i<=to;i++)
                result=op(result,numbers[i]);
            return result;
        }
        void MainFormLoad(object sender,EventArgs e)
        {
            int[] numbers=new int[7]{0,2,4,1,6,8,10};
            label1.Text=Process(Add,numbers,0,3).ToString()+"\n";
            label1.Text+=Process(Multiply,numbers,3,6).ToString();
        }

定义了多个两个方法Add和Multiply,和一个数组处理方法Process,它以委托方法作为参数处理数组

Action系列委托与MethodInvoker
Func泛型委托所能接收的方法都有返回值,Action系列委托是接收返回void的系统预定义委托
public delegate void Action();
public delegate void Action<T>(T obj);
public delegate void Action<T1,T2>(T1 arg1,T2 arg2);
public delegate void Action<T1,T2,T3>(T1 arg1,T2 arg2,T3 arg3);

使用方法和Func一样
MethodInvoker委托位于System.Windows.Forms中,声明如下:
public delegate void MethodInvoker();
和无类型参数的Action委托等价,用法也一样

Predicate<T>委托:
Predicate<T>委托在.NET基类库中经常出现,定义如下:
public delegate bool Predicate<T>(T obj);
此委托引用一个返回bool值的方法,在实际开发中,经常使用Prodicate<T>委托变量引用一个“判断条件函数”,在判断条件函数内部书写代码表明函数参数所引用的对象满足的条件,条件满足时,函数返回true,一个例子:
        class MyClass
        {
            public int Value;
            public string Info;
        }
        private static List<MyClass> GetMyClassList()
        {
            List<MyClass> lst = new List<MyClass>();
            Random ran = new Random();
            MyClass obj = null;
            for (int i = 0; i < 10; i++)
            {
                obj = new MyClass();
                obj.Value=ran.Next(1,100);
                obj.Info="object "+i.ToString();
                lst.Add(obj);
            }
            return lst;
        }
        static bool GreaterThan50(MyClass elem)
        {
            if (elem.Value > 50)
                    return true;
            return false;
        }
        void MainFormLoad(object sender,EventArgs e)
        {
            Predicate<MyClass> pred = GreaterThan50;
            List<MyClass> lst = GetMyClassList();
           MyClass foundElement= lst.Find(pred);
           if (foundElement != null)
               label1.Text=string.Format("找到了符合条件的对象。Infomation={0},Value={1}", foundElement.Info, foundElement.Value);
           else
               label1.Text="未找到符合条件的对象";
        }
生成一个List<MyClass>,并且查找其中MyClass对象的Value值大于50的输出信息
泛型集合List<T>中定义了一个Find方法:
public T Find(Predicate<T> match);
Lis<T>.Find方法遍历集合中的所有对象,并将每个对象作为Predicate<T>所引用的“判断条件函数”实参调用此函数。
使用Predicate<T>委托时,其判断条件一般是“外部硬性规定的”而非由数据自身指定,否则就不适合采用此类委托。

下节还有匿名方法与Lambda表达式、回调

你可能感兴趣的:(C#)