1、回调函数

    回调函数实际上是方法调用的指针,又称函数指针。.NET以委托的形式实现了函数指针的概念。

    但与C函数指针不同的地方在于:.NET委托是类型安全的。

    .NET中的方法依托于类实例。所以不能直接将方法作为参数传递。而如果要传递方法,必须把方法封装在委托对象中,委托对象一般简称为委托。委托包含了方法细节信息。

 

2、声明委托

delegate void VoidOperation(uint x);

   委托实现派生自System.MulticastDelegate,而System.MulticastDelegate又派生自System.Delegate。

 

3、使用委托

private delegate string GetAString();
int x = 40;
GetAString gas = x.ToString;  // 或者 GetAString gas = new GetAString(x.ToString);
gas();  // ToString()方法无参数,所以直接调用即可,返回 40

   C#语法中,委托总包含一个带一个参数的构造函数,这个参数就是委托引用的方法。且这个方法必须匹配最初定义的委托的签名。

   方法可以是实例方法,也可以是静态方法。注意上面的参数是x.ToString,而不是x.ToString(),后者表示方法执行的结果,前者才表示该方法。

   

4、匿名方法

   委托还有另外一种方式,将匿名方法传为委托的参数,如下:

private delegate string GetAString(string s);
GetAString gas = delegate(string param) 
{
    string s = "hello, " + param;
    return s;
 };
 gas("feichexia");  // 返回 hello, feichexia

   匿名方法的优点是减少了系统开销,方法仅在委托使用时才定义。且能减少代码复杂度。

   另外注意不要在匿名方法中使用跳转语句跳转到匿名方法外部,反之亦然。匿名方法内部不能访问外部的ref和out参数

 

5、委托版本冒泡排序

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace MyOnlineStore.DAC.Test
{
    public delegate bool CompareOp(object op1, object op2);

    public class Employee
    {
        private string _name;
        private decimal _salary;

        public Employee(string name, decimal salary)
        {
            this._name = name;
            this._salary = salary;
        }

        public override string ToString()
        {
            return string.Format(_name + ", {0:C}", _salary);
        }

        public static bool IsGreater(object obj1, object obj2)
        {
            Employee emp1 = (Employee) obj1;
            Employee emp2 = (Employee) obj2;

            return (emp1._salary>emp2._salary);
        }
    }

    public class BubbleSort
    {
        public static void Sort(object[] array, CompareOp gtMethod)
        {
            for (int i = 0; i < array.Length; i++)
            {
                for (int j = i + 1; j < array.Length; j++)
                {
                    if (gtMethod(array[j], array[i]))
                    {
                        object temp = array[i];
                        array[i] = array[j];
                        array[j] = temp;
                    }
                }
            }
        }

        public static void main()
        {
            Employee[] emps = 
            {
                new Employee("Bug", 20000),
                new Employee("Diary", 1000),
                new Employee("June", 12132),
                new Employee("July", 12300)
            };

            CompareOp compOp = Employee.IsGreater;
            BubbleSort.Sort(emps, compOp);
        }
    }
}

 

6、多播委托

    一个委托可以包含多个方法,如下:

delegate void CaculateOp(double val);
CaculateOp ops = MathOperations.MultiplyByTwo;
ops += MathOperations.DivideByTwo;

等价于

delegate void CaculateOp(double val);
CaculateOp op1 = MathOperations.MultiplyByTwo;
CaculateOp op2 = MathOperations.DivideByTwo;
CaculateOp ops = op1 + op2;

   多播委托可以识别 + += - -=(-和-=用于删除方法调用)

 

7、事件

btnOne.Click = new EventHandler(Button_Click);

   EventHandler实际上是委托类型,如下:

public delegate void EventHandler(object sender, EventArgs e); // sender是引发事件的对象,e包含事件有关信息

   所以Button_Click的方法签名也必须与此一致。可以为一个事件绑定多个事件处理方法,如下:

btnOne.Click = new EventHandler(Button_Click);
btnOne.Click += new EventHandler(Button_Click_2);

 

8、...

   

posted on 2012-08-15 21:49  feichexia  阅读(337)  评论(0编辑  收藏  举报