work hard work smart

专注于Java后端开发。 不断总结,举一反三。
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

委托和事件(无参数事件和有参数事件)

Posted on 2011-05-09 22:40  work hard work smart  阅读(5389)  评论(0编辑  收藏  举报

一、为什么使用委托【引用CSDN】

(1)在写类的时候,根本就不能确定要调用哪个对象的方法:例如,你把自己的一个对象上的方法挂在微软的textbox 的一个事件上。微软在写textbox时根本就不可能知道这个事件发生时,需要调用哪个对象的哪个方法,只有你自己去指定说需要调什么方法,并且以委托的方式挂在相应的事件上。
微软在写textbox的事件时,唯一能确定的是这个事件的格式,或者说这个事件需要调用的方法的格式,
类似于 button1_click(object sender, EnentArgs e) 等等。 只要是按照这个类型写的方法,都能被挂在这个事件上,并且在事件发生时,方法会被调用。这只是基于消息驱动的实现方式之一。

(2)想象一下如果把你“用嘴吃东西的过程”封装成一个类吧:
其中对于吃这个动作是这么定义的:
public void 吃(食物)
{
  把食物塞你嘴里(); // step 1
  嘴开始有所动作(食物); // step 2
  咽下去(是否可以咽下去); // step 3
}

注意步骤二,不同的食物你的嘴会采用不同的方式处理。
当食物==水,不会咀嚼直接咽
当食物==肉包子,当然要嚼嚼再咽
当食物==口香糖,只嚼不咽
当食物==鱼,你还要仔细的吐出鱼刺......
显然你不可能在你的类里预见到所有情形,这种情况下就可以把“嘴开始有所动作”考虑定义成委托,让客户端调用时给出具体实现,至于在类里,占个位而已。

二、实现委托的步骤

1.定义委托 
2.定义委托实例
3.将方法登记到委托实例中
4.如果委托有登记事件,则执行实例

举两个个简单的例子:

//无参数的情况   
 public class Test
    {
        private delegate void CatShoutHandle();
        private event CatShoutHandle CatShout;

        public void TestDelegate()
        {

            CatShout += new CatShoutHandle(c_CatShout);
            if (CatShout != null)
            {
                CatShout();
            }
        }

        void c_CatShout()
        {
            Console.WriteLine("This is my Test Delagate!");
        }

        static void Main()
        {

            Test c = new Test();
            c.TestDelegate();
            return;
        }
    }

  有参数情况

//有参数情况
 public class MyParameter:EventArgs
    {
        private string name;
        public MyParameter(string _name)
        {
            this.name = _name;
        }

        public string Name
        {
            get { return name; }
            set { name = value; }
        }
    }

    public class Test
    {
        private delegate void CatShoutHandle(object sender,MyParameter para);
        private event CatShoutHandle CatShout;

        public void TestDelegate()
        {

            CatShout += new CatShoutHandle(Test_CatShout);
            MyParameter para = new MyParameter("My test Parameter Name");
            if (CatShout != null)
            {
                CatShout(this,para);
            }
        }

        void Test_CatShout(object sender, MyParameter para)
        {
            Console.WriteLine("This is my Test Delagate! Parameter's name is: {0}",para.Name);
        }

    

        static void Main()
        {

            Test c = new Test();
            c.TestDelegate();
            return;
        }
    }

  

 三、下面的例子是一个没有使用事件并含有参数的委托 

 class clsDelegate
    {
        public delegate int simpleDelegate(int a, int b);
        public int addNumber(int a, int b)
        {
            return (a + b);
        }

        public int mulNumber(int a, int b)
        {
            return (a * b);
        }

        static void Main(string[] args)
        {
            clsDelegate clsDlg = new clsDelegate();
            simpleDelegate addDelegate = new simpleDelegate(clsDlg.addNumber);
            simpleDelegate mulDelegate = new simpleDelegate(clsDlg.mulNumber);
            if (addDelegate != null && mulDelegate != null)
            {
                int addAns = addDelegate(10, 12);
                int mulAns = mulDelegate(10, 10);
                Console.WriteLine("addNum method using a delegate: {0}", addAns);
                Console.WriteLine("mulNum method using a delegate: {0}", mulAns);
                Console.Read();
            }
        }
    }

 

四、匿名委托的使用

匿名委托是使用委托的另一种方式,使用匿名委托时,代码执行的不太快。编译器仍指定了一个方法,该方法只有一个指定的名称。在匿名方法内部不能访问不安全的代码,也不能在匿名方法外部使用ref和out参数。

  //匿名委托
        private delegate void TestDelegate2(int a);
        public void Eample2()
        {
            int a = 12;
            TestDelegate2 t = delegate(int x)
            { 
                Console.WriteLine("output x : {0}", x); 
            };
            t(a);
        }

        static void Main()
        {

            Test c = new Test();
            c.Eample2();
            return;
        }

  匿名委托示例2,跟上一个示例类似

class Program  
  {       
   delegate string delegateTest(string str);      
    static void Main(string[] args)  
     {         
         string second = ",second";       
         delegateTest test =  delegate(string para)        
        {             
         para += second;      
              para += ",third";       
             return para;         
       };          
      Console.WriteLine( test("first"));
   }
}

  

 五、下面是两个稍微复杂的例子

1.无参数事件

  class Program
{

static void Main(string[] args)
{
Cat cat
= new Cat("small cat");
Mouse mouse1
= new Mouse("small mouse1");
Mouse mouse2
= new Mouse("small mouse2");

//将Mouse的run方法通过实例化委托Cat.CatShoutEventHandlerd登记到CatShout中。
cat.CatShout += new Cat.CatShoutEventHandler(mouse1.Run);
cat.CatShout
+= new Cat.CatShoutEventHandler(mouse2.Run);

cat.CatShout
+= new Cat.CatShoutEventHandler(cat_CatShout);


cat.Shout();
Console.ReadLine();
}
static void cat_CatShout()
{

Console.WriteLine(
"cat is coming ,mouse3 run");
}

}

public class Cat
{
//声明委托
public delegate void CatShoutEventHandler();
public event CatShoutEventHandler CatShout;
private string _name;
public Cat(string name)
{
this._name = name;
}
public void Shout()
{
Console.WriteLine(
"miao, I am {0}", _name);
//如果CatShout中有对象登记事件,则执行CatShout()
if (CatShout != null)
CatShout();
}
}
  
public class Mouse
{
private string _name;
public Mouse(string name)
{
this._name = name;
}
public void Run()
{
Console.WriteLine(
"Cat is coming, {0} run", _name);
}
}

  

2.有参数事件

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

namespace weituo
{
    class Class1
    {
        static void Main(string[] args)
        {

            Cat cat = new Cat("small cat");
            Mouse mouse1 = new Mouse("small mouse1");
            Mouse mouse2 = new Mouse("small mouse2");

            //将Mouse的run方法通过实例化委托Cat.CatShoutEventHandlerd登记到CatShout中。
            cat.CatShout += new Cat.CatShoutEventHandler(mouse1.Run);
            cat.CatShout += new Cat.CatShoutEventHandler(mouse2.Run);

            cat.CatShout += new Cat.CatShoutEventHandler(cat_CatShout);

            cat.Shout();
            Console.ReadLine();
        }

        static void cat_CatShout(object sender, CatShoutEventArgs e)
        {
            Console.WriteLine("cat is coming ,mouse run");
        }

    }
    public class CatShoutEventArgs : EventArgs
    {
        private string _name;
        public CatShoutEventArgs(string name)
        {
            this._name = name;
        }

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    }
    public class Cat
    {

        //声明委托
        public delegate void CatShoutEventHandler(object sender, CatShoutEventArgs e);

        public event CatShoutEventHandler CatShout;
        private string _name;
        public Cat(string name)
        {
            this._name = name;
        }


        public void Shout()
        {
            Console.WriteLine("miao, I am {0}", _name);
            CatShoutEventArgs e = new CatShoutEventArgs(_name);
            //如果CatShout中有对象登记事件,则执行CatShout()
            if (CatShout != null)
                CatShout(this, e);

        }

    }

    public class Mouse
    {
        private string _name;
        public Mouse(string name)
        {
            this._name = name;
        }

        public void Run(object sender, CatShoutEventArgs args)
        {
            Console.WriteLine("Cat {0} is coming, {1} run", args.Name, _name);
        }
    }
}

  


3、WPF中的事件

 3.1 public Window1()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(Init);
        }
        void Init(object sender, RoutedEventArgs e)
        {
            button2.Click += new RoutedEventHandler(button2_Click);
            button3.Click += new RoutedEventHandler(button3Click);
        }
        void button3Click(object sender, RoutedEventArgs e)
        {
             MessageBox.Show("testbutton3"); 
       }
        void button2_Click(object sender, RoutedEventArgs e)
        {
           MessageBox.Show("testbutton2"); 
        }

 3.2DispatcherTimer的使用.  集成到按指定时间间隔和指定优先级处理的 Dispatcher队列中的计时器。

DispatcherTimer timer = new DispatcherTimer();

timer.Interval
= TimeSpan.FromSeconds(1);

this.Loaded += delegate

{

  
//处理函数

  button2_Click();

  timer.Stop();

};

timer.Start();


六、EventHandler泛型委托

    class EventHandlerTest
    {
        public static void TestEventHandler()
        {
            HasEvent has = new HasEvent();
            has.SampleEvent += new EventHandler<MyEventArgs>(has_SampleEvent);
            has.EventTest("work smart!");
            has.EventTest("work hard!");
        }

        static void has_SampleEvent(object sender, MyEventArgs e)
        {
            Console.WriteLine(e.Message);
        }
    }

    public class MyEventArgs:EventArgs
    {
        private string msg;

        public MyEventArgs(string message)
        {
            msg = message;
        }
        public string Message
        {
            get { return msg; }
            set { msg = value; }
        }
    }

    public class HasEvent
    {
        public event EventHandler<MyEventArgs> SampleEvent;

        public void EventTest(string str)
        {
            EventHandler<MyEventArgs> myEvent = SampleEvent;
            if (myEvent != null)
            {
                myEvent(this, new MyEventArgs(str));
            }
        }
    }