学习问题参考/解决/保留

自我控制应当成为生活的基调, 美好生活是理性来指导的并且紧紧抓住崇高的理想, 人的一生,就是进行尝试,尝试得越多,生活就越美好!
  博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

先定义一个委托如下:
public delegate void myEventHandler(int i,out string o);

再用MSIL反汇编程序(Ildasm.exe)来观看反汇编代码
其实CLR为我们做了4件事情
1.定义一个构造器
2.定义一个虚方法BeginInvoke
3.定义一个虚方法EndInvoke
4.定义一个虚方法Invoke

(1)在反汇编代码中我看到如下片断:
.class auto ansi sealed nested public myEventHandler
       extends [mscorlib]System.MulticastDelegate
{
} // end of class myEventHandler
由此可以知道其实我们声明的委托myEventHandler就是一个密封类
它的父类是System.MulticastDelegate
看到这里,我的一个疑惑被解除了
以前我也自己定义过委托,总是感觉好像在程序中到处都可以定义委托,在类里面和类的外部都可以定义,一直不知道为什么?
现在我基本明白了,其实委托是一个类,类可以在哪里定义,委托就可以在哪里定义。

(2)我们现在再来看看构造器
在这之前,有必要搞清楚委托的继承关系
System.Delegate
---System.MulticastDelegate
------ConsoleApplication1.myEventHandler

现在我们实例化一个委托:
myEventHandler my=new myEventHandler(staticCall);
实际上它是在调用这个委托的构造器

下面的是这个构造器的代码:
public myEventHandler(object @object, IntPtr method);
第一个参数应该是类实例的实例
第二个参数应该是委托的方法信息

这个构造器会再调用它父类的构造器,父类构造器代码如下:
protected MulticastDelegate(object target, string method) : base(target, method)
{
}
最终调用的是System.Delegate的构造器
protected Delegate(object target, string method)
这个构造器是对类System.Delegate的2个私有字段进行处理
private object _target;
private RuntimeMethodInfo _method;

System.Delegate类有2个公有属性可以得到上述2个私有字段的数值:
1.Method
获取委托所表示的方法
2.Target
获取类实例,当前委托将对其调用实例方法
如果是静态方法,则为空引用


费话少说,我们来段代码看看效果
建立一个我最爱的控制台程序,代码如下:

 1using System;
 2using System.Reflection;
 3
 4namespace ConsoleApplication1
 5{
 6    class Class1
 7    {
 8        public delegate void myEventHandler(int i,out string o);
 9        /// <summary>
10        /// 应用程序的主入口点。
11        /// </summary>

12        [STAThread]
13        static void Main(string[] args)
14        {
15            Class1 c=new Class1();
16            myEventHandler my=new myEventHandler(staticCall);
17
18            if (my.Target==null)
19            {
20                Console.WriteLine("我们调用的类静态方法");
21            }

22            else
23            {
24                Console.WriteLine("我们调用的类实例名称为:"+my.Target.ToString());
25            }

26            
27            MemberInfo info=my.Method;
28            
29            Console.WriteLine("此方法的基本信息:"+ my.Method.ToString() );
30            Console.WriteLine( my.Method.IsStatic?"此方法是一个静态方法":"此方法是一个实例方法" );
31            Console.WriteLine( "此方法的名称为:"+info.Name );
32
33            Console.ReadLine();
34        }

35
36        public void call(int i,out string o)
37        {
38            o="haha";
39        }

40
41        
42        public static void staticCall(int i,out string o)
43        {
44            o="haha";
45        }

46    }

47}

48

我们可以看到结果


要是把代码中16行替换为
myEventHandler my=new myEventHandler(staticCall);
我们可以看到结果



(3)再来看看委托的虚方法BeginInvoke和虚方法EndInvoke
它的代码原型如下:
public virtual IAsyncResult BeginInvoke(int i, out string o, AsyncCallback callback, object @object);
public virtual void EndInvoke(out string o, IAsyncResult result);

BeginInvoke 异步方法签名的规则是:
包括所有 IN 参数。
包括所有 OUT 参数。
包括所有 IN/OUT 参数。
包括所有 ByRef 参数。
将 AsyncCallback 和 AsyncState(可通过 IAsyncResult 接口的 AsyncState 属性获得)作为最后两个参数。
返回 IAsyncResult

EndInvoke 异步方法签名的规则是:
包括所有 IN/OUT 参数。
包括所有 OUT 参数。
包括所有 ByRef 参数。
将 IAsyncResult 作为最后一个参数。

这2个方法提供了委托的异步编程方法支持。


(4)再来看看委托的方法Invoke
它的签名和委托的签名是一样的,实际上是委托的同步编程方法.
实际上是通过它来回调我们委托的方法。

我知道在异步编程中,我们可以利用委托实例直接调用BeginInvoke和EndInvoke方法
那为什么在同步编成中,VS2003不允许我们直接在程序中调用Invoke方法?
一直没明白这个问题,WHY?

还有一个疑问:
我用Reflector(版本是4.1)看到的Invoke方法如下:
public override void Invoke(int i, out string o);
它是一个重写的方法

而我用ildasm.exe看到Invoke方法却是virtual的

其实我更相信后者
因为我查看了myEventHandler的父类中好像没有定义Invoke方法

不知道,大家有什么看法?