代码改变世界

C#委托delegate

2013-05-11 18:40  hduhans  阅读(243)  评论(0)    收藏  举报

一、初级版,有了委托呢,我们就可以像传递变量一样的传递方法。在JavaScript,PHP等弱类型语言中,本身就支持方法作为另一方法的参数进行传递。

  1) 参考代码:

public class Program
{
    public delegate void delegateGreeting(String name);  //定义个方法委托 该委托支持调用具有相同参数的方法
  
   //此处可用Func委托简化使用,
   //public static void GreetPeople(String name,Func<String,String> fun)
//{ fun(name); }
public static void GreetPepole(String name, delegateGreeting MakeGreeting) { MakeGreeting(name); } public static void EnglishGreeting(String name) { Console.WriteLine("Moring," + name); } public static void ChineseGreeting(String name) { Console.WriteLine("你好," + name); } static void Main(string[] args) { GreetPepole("hans", EnglishGreeting); GreetPepole("小刚", ChineseGreeting); Console.Read(); } }

  可以看出,委托是一个类,它定义了方法的类型,使得可以将方法当作另一个方法的参数来进行传递,这种将方法动态地赋给参数的做法,可以避免在程序中大量使用If-Else(Switch)语句,同时使得程序具有更好的可扩展性。

  2) 使用委托可以将多个方法绑定到同一个委托变量,调用多个方法

static void Main(string[] args)
{
    delegateGreeting de;
    de = EnglishGreeting;
    de += ChineseGreeting;
    GreetPepole("hans", de);  //委托对象按顺序调用两个两个方法
    Console.Read();
}

   

二、高级版。观察者设计模式通常使用使用委托和事件。这有一个热水器、监视器、警报器的应用案例,给热水器通上电,当水温超过95度时,监视器显示水温,警报器发出警报,提示水快烧开了。

//热水器
public class Heater
{
    private int temperature;
    public string type = "my type";
    public string area = "China Hangzhou";

    //声明委托  命名规则 以Eventhandler结尾
    public delegate void BoiledEventHandler(Object sender, BoiledEventArgs e);
    //声明事件  命名规则 以Event结尾
    public event BoiledEventHandler BoiledEvent;

    public class BoiledEventArgs : EventArgs
    {
        public readonly int temperature;
        public BoiledEventArgs(int temperature) {
            this.temperature = temperature;
        }
    }

    protected virtual void OnBoiled(BoiledEventArgs e) {
        if (BoiledEvent != null) {
            BoiledEvent(this,e);
        }
    }

    //烧水
    public void BoilWater() {
        for (int i = 0; i <= 100; i++) {
            temperature = i;

            if (temperature > 95) {
                BoiledEventArgs e = new BoiledEventArgs(temperature);
                OnBoiled(e);
            }
        }
    }
}

//警报器
public class Alarm {
    public void MakeAlert(Object sender, Heater.BoiledEventArgs e) {
        Heater heater = (Heater)sender;

        Console.WriteLine("Alarm:{0}-{1}",heater.area,heater.type);
        Console.WriteLine("Alarm:嘀嘀嘀,水已经{0}度",e.temperature);
        Console.WriteLine();
    }
}

//监视器
public class Display {
    public void ShowMsg(Object sender, Heater.BoiledEventArgs e) {
        Heater heater = (Heater)sender;

        Console.WriteLine("Display:{0}-{1}",heater.area,heater.type);
        Console.WriteLine("Display:水快烧开了,当前水温{0}度",e.temperature);
        Console.WriteLine();
    }
}

//...使用方法
Heater heater = new Heater();
heater.BoiledEvent += new Heater.BoiledEventHandler((new Alarm()).MakeAlert);
heater.BoiledEvent += (new Display()).ShowMsg;
heater.BoilWater();

 

三、申明委托

  1) delegate。至少0个参数,参数个数[0~32],返回值可有可无。如:public delegate int deleteAdd(int x,int y);

      注意到,在delegate委托定义中,最重要的是参数类型(int x,int y)和返回值(int),由此引入了下面的委托简写。

  2) Action,Action表示无返回值的泛型委托,参数个数[0~16]。

    a、Action 表示无参,无返回值的委托;

    b、Action<int,int> 表示传入参数int,int无返回值的委托;

  3) Func,Func表示有返回值的泛型委托,最后一个参数为返回值,参数个数[0~16]。

      a、Func<int> 表示无参,返回值为int的委托;

    b、Func<int,String> 表示传入参数int,返回值为String的委托;

    c、委托与匿名方法,定义如:Func<String,String> fun = delegate(String s){ return s.ToUpper(); }

    d、委托与lambda表达式,定义如:Func<String,String> fun = x=>x.ToUpper();   --普通lambda表达式

                   或 Func<String,String> fun = x=>{ Console.WrieLine(x); };    --定义方法

  4) predicate,表示返回bool类型的泛型委托。predicate有且只有一个参数,返回值固定为bool,参数个数[1];

   

 C#函数之惰性求值

http://www.cnblogs.com/yaozhenfa/p/functional_lazy.html