积极答复者
关于委托的问题

问题
-
我写了两段代码:
第一段:
namespace TestConsoleApplication1 { class Program { static void Main(string[] args) { Program p = new Program(); p.eventHandler += p.ClickMeFirst; p.eventHandler += p.ClickMeSecond; p.eventHandler(new object()); Console.Read(); } OnClickMeEventHandler eventHandler; public void ClickMeFirst(object sender) { Console.WriteLine("ClickMe First!"); } public void ClickMeSecond(object sneder) { Console.WriteLine("ClickMe Second!"); } } delegate void OnClickMeEventHandler(object sender); }
第二段:namespace TestConsoleApplication1 { class Program { static void Main(string[] args) { Program p = new Program(); OnClickMeEventHandler eventHandler; eventHandler += p.ClickMeFirst; eventHandler += p.ClickMeSecond; eventHandler(new object()); Console.Read(); } public void ClickMeFirst(object sender) { Console.WriteLine("ClickMe First!"); } public void ClickMeSecond(object sneder) { Console.WriteLine("ClickMe Second!"); } } delegate void OnClickMeEventHandler(object sender); }
这两段代码几乎是一样的,区别在于第二段代码将 OnClickMeEventHandler eventHandler; 这一句由Program类的内部移到了Main函数内。结果却是大相径庭,第一段代码正常运行,第二段代码编译错误:
错误 1 使用了未赋值的局部变量“eventHandler”
于是我得出结论,在类内部声明一个delegate作为局部变量和在某函数内部声明一个delegate相比,该delegate初始化方式或者说步骤应该是有区别的。
请问是否是这样?如果是,那么这区别是什么?为什么有这样的区别?如果不是,那为什么第二段代码编译出错呢?
谢谢!
答案
-
你好:)
“委托”是一种特殊的类型。它定义以后必须和普通类型一样,必须“先声明,后使用“。
第一个例子中,显然class Program的变量eventHandler的类型是委托,且依附于p的实例上,那么p实例化以后就可以直接使用了(使用+=多路委托)。
至于第二个例子——你虽然直接声明了临时变量,但是在Main函数中,直接使用多路委托+=是不可以的,因此只能使用以下形式——
static void Main(string[] args)
{
OnClickMeEventHandler eventHandler;
Program p = new Program();
eventHandler = new OnClickMeEventHandler(p.ClickMeFirst);
eventHandler += new OnClickMeEventHandler(p.ClickMeSecond);eventHandler(new object());
Console.Read();
}
如果你有其它意见或私下交流,请发送邮件到:maledong@qq.com;或者请
下载MSDN桌面工具(Vista,Win7)
下载Technet桌面小工具(Vista,Win7)
慈善点击,点击此处- 已标记为答案 沉默的老虎 2011年6月13日 2:12
-
问的好!
“+=”在委托中——如果这个委托是一个类的一部分(是类的变量),那么在使用“+=”的时候,其实是自动通过编译器“语法糖”功能自动调用了Delegate.Combine函数,我用Reflector反编译了第一个程序:
private static void Main(string[] args)
{
Program p;
new Program { eventHandler = (OnClickMeEventHandler) Delegate.Combine(p.eventHandler, new OnClickMeEventHandler(p.ClickMeFirst)), eventHandler = (OnClickMeEventHandler) Delegate.Combine(p.eventHandler, new OnClickMeEventHandler(p.ClickMeSecond)) }.eventHandler(new object());
Console.Read();
}显然,使用Combine函数把多个委托串接起来,自然达到“多米诺骨牌”的串接效应。
但是,如果是第二个程序,那么直接使用的话——因为单独声明一个临时的委托类型,系统不会特殊处理,只会按照普通变量处理,没有初始化自然出错了。
如果你有其它意见或私下交流,请发送邮件到:maledong@qq.com;或者请
下载MSDN桌面工具(Vista,Win7)
下载Technet桌面小工具(Vista,Win7)
慈善点击,点击此处- 已标记为答案 沉默的老虎 2011年6月13日 2:12
全部回复
-
你好:)
“委托”是一种特殊的类型。它定义以后必须和普通类型一样,必须“先声明,后使用“。
第一个例子中,显然class Program的变量eventHandler的类型是委托,且依附于p的实例上,那么p实例化以后就可以直接使用了(使用+=多路委托)。
至于第二个例子——你虽然直接声明了临时变量,但是在Main函数中,直接使用多路委托+=是不可以的,因此只能使用以下形式——
static void Main(string[] args)
{
OnClickMeEventHandler eventHandler;
Program p = new Program();
eventHandler = new OnClickMeEventHandler(p.ClickMeFirst);
eventHandler += new OnClickMeEventHandler(p.ClickMeSecond);eventHandler(new object());
Console.Read();
}
如果你有其它意见或私下交流,请发送邮件到:maledong@qq.com;或者请
下载MSDN桌面工具(Vista,Win7)
下载Technet桌面小工具(Vista,Win7)
慈善点击,点击此处- 已标记为答案 沉默的老虎 2011年6月13日 2:12
-
嗯,你说的对,不能使用 += 是由于eventHandler没有初始化引起的。
不过,如果我手动对eventHandler进行初始化,就必须写成 eventHandler = new OnClickMeEventHandler(p.ClickMeFirst) 这样的形式。
而不能写成 OnClickMeEventHandler eventHandler = new OnClickMeEventHandler() 这样的形式。
这样会有一个编译错误“错误 1 “TestConsoleApplication1.OnClickMeEventHandler”不包含采用“0”参数的构造函数 “”
那么问题又来了,我的第一段代码中Program类中的OnClickMeEventHandler在Program实例化为P的时候是如何进行初始化的?
-
问的好!
“+=”在委托中——如果这个委托是一个类的一部分(是类的变量),那么在使用“+=”的时候,其实是自动通过编译器“语法糖”功能自动调用了Delegate.Combine函数,我用Reflector反编译了第一个程序:
private static void Main(string[] args)
{
Program p;
new Program { eventHandler = (OnClickMeEventHandler) Delegate.Combine(p.eventHandler, new OnClickMeEventHandler(p.ClickMeFirst)), eventHandler = (OnClickMeEventHandler) Delegate.Combine(p.eventHandler, new OnClickMeEventHandler(p.ClickMeSecond)) }.eventHandler(new object());
Console.Read();
}显然,使用Combine函数把多个委托串接起来,自然达到“多米诺骨牌”的串接效应。
但是,如果是第二个程序,那么直接使用的话——因为单独声明一个临时的委托类型,系统不会特殊处理,只会按照普通变量处理,没有初始化自然出错了。
如果你有其它意见或私下交流,请发送邮件到:maledong@qq.com;或者请
下载MSDN桌面工具(Vista,Win7)
下载Technet桌面小工具(Vista,Win7)
慈善点击,点击此处- 已标记为答案 沉默的老虎 2011年6月13日 2:12