• 如何重载delegate


    在写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发生冲突了。

    不过最后需要补充的是,重载delegate这样的说法并不正确,其实只是定义了不同类型的delegate,而非发生了重载操作。

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

  • 相关阅读:
    C#文件操作
    C# 本地txt文件读取至comboBox下拉列表
    自动部署war包脚本
    设置eclipse包资源管理器的背景色
    Failed to connect to ourself!错误解决办法
    Keepalived+LVS+MysqlCluster(7.1.10)架构方案(一)
    Mysql Cluster在线添加数据节点
    在Linux下使用perl通过unixODBC连接SQLServer2000
    MySQL中四舍五入的实现
    关于Temporary error: 1218错误的思考
  • 原文地址:https://www.cnblogs.com/sjyforg/p/3231280.html
Copyright © 2020-2023  润新知