将C#转换为VB,NET:具有返回类型的委托类型的事件

时间:2017-04-02 23:18:00

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

这是用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.UnitResolve方法内的GetUnitByName()调用此错误消息:

  

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

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

2 个答案:

答案 0 :(得分:3)

将值从事件处理程序返回到事件调用的常规方法是通过参数---事件参数类的成员,或通过委托上的ByRef参数。 / p>

如果您可以控制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语言,则可以跳过空检查并使用?.运算符,这对于特定的线程安全问题也应该是安全的。

答案 1 :(得分:1)

原始C#源代码不好;事件处理程序不应返回值。你必须把它变成非事件:

Public UnitResolve As UnitResolveEventHandler

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

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