2008-10-15 15 views
19

Creo que el siguiente código VB.Net es el equivalente al código C# anterior; sin embargo, falla la prueba VB.Net: nunca se llama al evento que maneja Lambda.¿Cómo declarar los controladores de eventos lambda en VB.Net?

¿Qué está pasando? Versión

VB.Net - falla:

<TestFixture()> _ 
Public Class TestClass 
    <Test()> _ 
    Public Sub EventTest() 
     Dim eventClass As New EventClass 
     Dim eventRaised As Boolean = False 
     AddHandler eventClass.AnEvent, Function() (eventRaised = True) 
     eventClass.RaiseIt() 
     Assert.IsTrue(eventRaised) 
    End Sub  
End Class 

Public Class EventClass 
    Public Event AnEvent() 
    Public Sub RaiseIt() 
     RaiseEvent AnEvent() 
    End Sub 
End Class 

C# versión - pases:

[TestFixture] 
    public class TestClass 
    { 
     [Test] 
     public void EventTest() 
     { 
      var eventClass = new EventClass(); 
      var eventRaised = false; 
      eventClass.AnEvent +=() => { eventRaised = true; }; 
      eventClass.RaiseIt(); 
      Assert.IsTrue(eventRaised); 
     } 
    } 

    public class EventClass 
    { 
     public delegate void EventHandler(); 
     public event EventHandler AnEvent; 
     public void RaiseIt() 
     { 
      AnEvent(); 
     } 
    } 

Respuesta

16

Nota: Esto se relaciona con las versiones anteriores de VB.net Antes de Visual Studio 2010 y VB.net 10

La diferencia es th en VB.Net una expresión lambda debe devolver un valor, es decir, deben ser funciones no subs. La expresión lambda eventRaised = true se interpreta como una expresión booleana en lugar de una asignación, es decir, se evalúa como falsa en lugar de establecerse como verdadera.

Más detalles sobre MSDN.

No creo que el patrón C# para probar los eventos utilizados en el ejemplo se pueda realizar en VB.Net sin introducir otra función, p.

<TestFixture()> _ 
Public Class Test 
    <Test()> _ 
    Public Sub EventTest() 
     Dim eventClass As New EventClass 
     Dim eventRaised As Boolean = False 
     AddHandler eventClass.AnEvent, Function() (SetValueToTrue(eventRaised)) 
     eventClass.RaiseIt() 
     Assert.IsTrue(eventRaised) 
    End Sub 

    Private Function SetValueToTrue(ByRef value As Boolean) As Boolean 
     value = True 
     Return True 
    End Function 

End Class 

Public Class EventClass 
    Public Event AnEvent() 
    Public Sub RaiseIt() 
     RaiseEvent AnEvent() 
    End Sub 
End Class 
+14

Realmente chillaban con lambdas en VB.Net. – chrissie1

+0

De acuerdo, parece que hicieron lo mínimo para poner el enlace en marcha y eso fue todo. –

+4

Tenga en cuenta que a partir de VS2010 las lambdas VB.Net ahora pueden ser subrutinas y no necesitan devolver un valor. –

2

Larga historia corta, no se puede hacer eso en VB por el momento (que está en la lista de características consideradas para la próxima versión). Debe usar un método declarado y el operador AddressOf.

El equipo de VB no tuvo tiempo de incluir delegados anónimos en el idioma (que es lo que está tratando de usar, técnicamente no es una expresión lambda).

Expresiones Lambda que tuvieron que implementar para que Linq realmente pueda funcionar. Los delegados anónimos no son requeridos por nada (pero serían bastante útiles). Supongo que pasaron más tiempo envolviendo cosas como Linq To XML y XML liteterals e integrando más operadores de consulta en la sintaxis ...

+0

Entendido que este es un delegado anónimo y no una expresión lambda. Sin embargo, ¿es el siguiente (que sí funciona) un delegado anónimo en VB ?: AddHandler eventClass.AnEvent, Function() (SetValueToTrue (eventRaised)) –

15

Para aquellos que encuentran esta pregunta ahora: desde Visual Basic 2010 (VB 10.0), anónimo Sub s hacer el trabajo, por lo que puede escribir algo como:

Sub() eventRaised = True 
+0

¿Qué sucede si más de una instrucción sigue a Sub()? –

+1

@LeiYang Luego puede hacer: 'Sub() instrucción1 instrucción2 End Sub' (son cuatro líneas). – svick

Cuestiones relacionadas