【问题标题】:Convert C# to VB,NET: Event with a delegate type that has a return type将 C# 转换为 VB、NET:具有返回类型的委托类型的事件
【发布时间】:2017-08-27 17:25:20
【问题描述】:

这是用 C# 编写的原始源代码

public delegate Unit UnitResolveEventHandler(object sender, ResolveEventArgs args);

public event UnitResolveEventHandler UnitResolve;

public static Unit GetUnitByName(string name) {
    Instance.unitsByName.TryGetValue(name, out result);
    if (Instance.UnitResolve != null) {
        foreach (UnitResolveEventHandler handler in Instance.UnitResolve.GetInvocationList()) {
            result = handler(Instance, new ResolveEventArgs(name));
        }
    }
}

使用在线翻译器,我得到了这个 VB.NET 代码:

Public Delegate Function UnitResolveEventHandler(sender As Object, args As ResolveEventArgs) As Unit

Public Event UnitResolve As UnitResolveEventHandler

Public Shared Function GetUnitByName(name As String) As Unit
    Instance.unitsByName.TryGetValue(name, result)
    If Instance.UnitResolve IsNot Nothing Then
        For Each handler As UnitResolveEventHandler In Instance.UnitResolve.GetInvocationList()
            result = handler(Instance, New ResolveEventArgs(name))
        Next
    End If
End Function

编译器用以下错误消息标记事件声明:

不能使用具有返回类型的委托类型来声明事件。

Instance.UnitResolveGetUnitByName() 方法内调用并显示以下错误消息:

Public Event UnitResolve As UnitResolveEventHandler' 是一个事件,并且 不能直接调用。

如何在不丢失功能的情况下正确地将代码从 C# 转换为 VB.NET?

【问题讨论】:

    标签: c# .net vb.net events code-translation


    【解决方案1】:

    原来的C#源代码不好;事件处理程序不应返回值。你必须让它不是事件:

    Public UnitResolve As UnitResolveEventHandler
    

    并手动使用Delegate.Combine 来添加事件处理程序:

    Instance.UnitResolve = Delegate.Combine(Instance.UnitResolve, newHandler)
    

    【讨论】:

      【解决方案2】:

      将值从事件处理程序返回到事件调用的惯用方式是通过参数——事件参数类的成员,或通过委托上的 ByRef 参数。

      如果您可以控制ResolveEventArgs 和事件处理程序例程,您可以执行以下操作:

      Public Class ResolveEventArgs
          '...
          Public ReturnValue As Unit
          '...
      End Class
      

      在处理程序的主体中(假设事件参数的典型声明为e),而不是Return (return value)

      e.ReturnValue = (return value) 'substitute for (return value) as appropriate
      

      然后,For Each 循环的主体将如下所示:

      Dim args As New ResolveEventArgs(name)
      handler(Instance, args)
      result = args.ReturnValue
      

      顺便说一句,原始 C# 代码存在线程安全问题。如果在 null 检查和读取调用列表之间删除了最后一个订阅的处理程序,它可能会抛出 NullReferenceException。这是否严重(或根本不是问题)取决于它的使用地点和方式。解决此问题的常用方法是存储到临时文件,然后在临时文件上执行空值检查和调用列表。如果您使用的是最新版本的 .NET 语言,则可以跳过空值检查并使用 ?. 运算符,这对于特定的线程安全问题也应该是安全的。

      【讨论】:

      • 错字:空条件运算符是?.
      • @piedar 谢谢,已修复。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-03-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多