如何重载delegate_.NET_编程开发_程序员俱乐部

中国优秀的程序员网站程序员频道CXYCLUB技术地图
热搜:
更多>>
 
您所在的位置: 程序员俱乐部 > 编程开发 > .NET > 如何重载delegate

如何重载delegate

 2013/8/1 23:13:03  申江渔夫  博客园  我要评论(0)
  • 摘要:在写delegate的时候遇到一个问题,在已有一个不带参数的delegate基础上,试图再增加一个带参数的delegate,结果VS报了“alreadycontainsadefinitionfor‘InvokeDelegate’”这样的错误。第一眼看上去,代码似乎没什么问题:1privatedelegatevoidInvokeDelegate();2privatedelegatevoidInvokeDelegate(stringparam)
  • 标签:重载

在写delegate的时候遇到一个问题,在已有一个不带参数的delegate基础上,试图再增加一个带参数的delegate,结果VS报了“already contains a definition for ‘InvokeDelegate’”这样的错误

第一眼看上去,代码似乎没什么问题:

1 private delegate void InvokeDelegate();  
2 private delegate void InvokeDelegate(string param);  

其实这是把delegate等同于了method,所以才会认为使用method的重载方式也可以重载delegate。

翻过《CLR via C#》这本书,或者直接用ILDASM工具查看就会明白,delegate在编译时会被编译器翻译成一个继承MulticastDelegate的类。

因此,delegate真实的代码应该是这样的:

 1 private sealed class InvokeDelegate : MulticastDelegate
 2 {
 3     public InvokeDelegate(Object object, IntPtr method);
 4     public virtual void Invoke();
 5     public IAsyncResult BeginInvoke(AsyncCallback callback, Object object);
 6     public virtual void EndInvoke(IAsyncResult result);
 7 }
 8  
 9 private sealed class InvokeDelegate : MulticastDelegate
10 {
11     public InvokeDelegate(Object object, IntPtr method);
12     public virtual void Invoke();
13     public IAsyncResult BeginInvoke(string param, AsyncCallback callback, Object object);
14     public virtual void EndInvoke(IAsyncResult result);
15 }

这样就不难看出,之前的写法会生成同样名称的两个类,这个当然是不被允许的。而两者唯一的区别就在于BeginInvoke方法中的参数。

那么是否就没有办法重载delegate了呢?

再看看.NET Framework中已有的Action委托。Action,Action,Action……各种形式都有。看一下它们的语法。

Action委托:public delegate void Action()
Action委托:public delegate void Action(T obj)
Action委托:public delegate void Action(T1 arg1, T2 arg2)

显然使用泛型的方式可以实现重载delegate的需求。

如果把“private delegate void InvokeDelegate(string param);”改成“private delegate void InvokeDelegate<in T>(T param);”,会生成以下的新类。

1 private sealed class InvokeDelegate<T> : MulticastDelegate
2 {
3     public InvokeDelegate(Object object, IntPtr method);
4     public virtual void Invoke(T param);
5     public IAsyncResult BeginInvoke(T param, AsyncCallback callback, Object object);
6     public virtual void EndInvoke(IAsyncResult result);
7 }

这种写法便不会与第一个delegate发生冲突了。

原文同步发布于我的个人博客

发表评论
用户名: 匿名