一、为什么使用委托【引用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));
}
}
}