“AddressOf”表达式在此上下文中不起作用,因为“AddressOf”的方法参数需要轻松转换为事件的委托类型

在事件处理程序上下文中使用此方法时 AddressOf ,会出现此警告,其中方法签名与事件的委托签名不完全匹配。 Visual Basic 允许 在这些方案中轻松转换委托 ,但 AddressOf 运算符变得冗余,因为编译器必须无论如何创建包装器委托。

了解宽松的委托转换

Visual Basic 允许你向委托分配方法,即使其签名不匹配,只要转换是安全的。 这称为 宽松的委托转换 ,包括:

  • 扩大的参数类型:方法参数可以是比委托参数更宽的类型。
  • 扩大的返回类型:方法返回类型可以比委托返回类型窄。
  • 省略的参数:方法的参数可能少于委托。
  • 已删除的返回值:可以将函数分配给 Sub 委托。

发生此警告时

当 Visual Basic 可以通过宽松的转换来处理分配时,会出现此警告,这会导致显式 AddressOf 不必要的作。

显示警告的完整示例

以下示例演示一个生成BC42328的方案:

Public Class DocumentProcessor
    ' Standard .NET event using EventHandler
    Public Event DocumentProcessed As EventHandler
    
    ' Custom event with different signature
    Public Event StatusChanged As Action(Of String)
    
    ' Handlers with different signatures
    
    ' Exact match for EventHandler - no warning
    Private Sub OnDocumentProcessed_Exact(sender As Object, e As EventArgs)
        Console.WriteLine("Document processed (exact signature)")
    End Sub
    
    ' Simplified handler - causes BC42328 with EventHandler
    Private Sub OnDocumentProcessed_Simple()
        Console.WriteLine("Document processed (simple)")
    End Sub
    
    ' Handler for custom event - exact match
    Private Sub OnStatusChanged_Exact(message As String)
        Console.WriteLine($"Status: {message}")
    End Sub
    
    ' Handler with ignored parameters - causes BC42328 with custom event
    Private Sub OnStatusChanged_Simple()
        Console.WriteLine("Status changed")
    End Sub
    
    Public Sub DemonstrateWarnings()
        Console.WriteLine("Setting up event handlers...")
        
        ' These work without warnings (exact matches)
        AddHandler DocumentProcessed, AddressOf OnDocumentProcessed_Exact
        AddHandler StatusChanged, AddressOf OnStatusChanged_Exact
        
        ' These generate BC42328 warnings (relaxed conversions)
        AddHandler DocumentProcessed, AddressOf OnDocumentProcessed_Simple
        AddHandler StatusChanged, AddressOf OnStatusChanged_Simple
        
        ' Fire the events
        RaiseEvent DocumentProcessed(Me, EventArgs.Empty)
        RaiseEvent StatusChanged("Processing complete")
    End Sub
    
    Public Sub DemonstrateSolutions()
        Console.WriteLine("Using solutions to avoid warnings...")
        
        ' Solution 1: Assign to variable first
        Dim handler1 As EventHandler = AddressOf OnDocumentProcessed_Simple
        AddHandler DocumentProcessed, handler1
        
        ' Solution 2: Use lambda expression
        AddHandler DocumentProcessed, Sub(s, e) OnDocumentProcessed_Simple()
        
        ' Solution 3: Direct assignment to delegate variable
        Dim handler2 As Action(Of String) = AddressOf OnStatusChanged_Simple
        AddHandler StatusChanged, handler2
        
        ' Fire the events
        RaiseEvent DocumentProcessed(Me, EventArgs.Empty)
        RaiseEvent StatusChanged("All solutions work")
    End Sub
End Class

编译此代码时,对于使用宽松委托转换的语句,Visual Basic 会显示 BC42328 警告AddHandler

为什么 AddressOf 似乎“不起作用”

警告消息指出 AddressOf “不起作用”,因为 Visual Basic 必须为宽松转换创建包装器委托,而不管怎样。 运算符 AddressOf 不会更改编译器处理转换的方式:无论在宽松转换方案中是否使用 AddressOf ,都会出现相同的结果。

但是, AddressOf 在语法上仍需要 AddHandler 语句和 RemoveHandler 语句。

错误 ID: BC42328

更正此错误

有几个选项,具体取决于你的需求。 使用前面示例中的示例 DocumentProcessor ,下面是解决BC42328警告的不同方法:

选项 1:首先分配给变量(保留确切的语义)

Public Sub DemonstrateHandler()
    ' Create delegate variable first - this eliminates the warning
    Dim handler As EventHandler = AddressOf OnDocumentProcessed_Simple
    AddHandler DocumentProcessed, handler
End Sub

选项 2:完全匹配委托签名

' Change the method signature to match EventHandler exactly
Private Sub OnDocumentProcessed_Simple(sender As Object, e As EventArgs)
    ' You can ignore the parameters if you don't need them
    Console.WriteLine("Document processed (simple)")
End Sub

Public Sub DemonstrateHandler()
    ' Now this works without warning
    AddHandler DocumentProcessed, AddressOf OnDocumentProcessed_Simple
End Sub

选项 3:使用 lambda 表达式

Public Sub DemonstrateHandler()
    ' Wrap the method call in a lambda that matches the signature
    AddHandler DocumentProcessed, Sub(sender, e) OnDocumentProcessed_Simple()
    
    ' Or create a more complex lambda inline
    AddHandler DocumentProcessed, 
        Sub(sender, e) 
            Console.WriteLine($"Event from {sender}")
            OnDocumentProcessed_Simple()
        End Sub
End Sub

选项 4:使用 Handles 子句(如果适用)

Public Class DocumentHandler
    ' Declare the event source with WithEvents
    Private WithEvents processor As DocumentProcessor
    
    ' Use Handles clause - no AddHandler needed
    Private Sub OnDocumentComplete() Handles processor.DocumentProcessed
        Console.WriteLine("Document processing is done!")
    End Sub
End Class

选项 5:直接分配给委托变量

Public Sub DemonstrateHandler()
    ' Assign to delegate variable then use with AddHandler
    Dim handler As EventHandler = AddressOf OnDocumentProcessed_Simple
    AddHandler DocumentProcessed, handler
End Sub

何时可以忽略此警告

在以下情况下,通常可以忽略此警告:

  • 处理程序方法有意省略不需要的参数。
  • 你使用的是更简单的方法签名,用于更简洁的代码。
  • 应用程序的性能影响微不足道。
  • 你正在制作原型或编写快速实用工具代码,其中清晰度比效率更重要。

宽松转换正常工作;此警告只是指示一个轻微的效率注意事项。 编译器会自动创建一个包装委托,这会增加一些性能负担,但不会影响功能。

何时忽略是适当的示例

Public Class QuickLogger
    Public Event LogMessage As Action(Of String, DateTime)
    
    ' Simple handler that ignores the timestamp parameter
    Private Sub WriteToConsole()
        Console.WriteLine("Something was logged")
    End Sub
    
    Public Sub SetupLogging()
        ' This generates BC42328, but it's fine for simple scenarios
        AddHandler LogMessage, AddressOf WriteToConsole
    End Sub
End Class

另请参阅