Как объявить обработчики событий lambda в VB.Net?
Я считаю, что следующий код VB.Net является эквивалентом существующего кода С#; однако тест VB.Net терпит неудачу - обработка событий Lambda никогда не вызывается.
Что происходит?
Версия VB.Net - не удается:
<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
Версия С# - проходит:
[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();
}
}
Ответы
Ответ 1
Примечание.. Это относится к более старым версиям VB.net до Visual Studio 2010 и VB.net 10
Разница заключается в том, что в VB.Net выражение lambda должно возвращать значение, то есть они должны быть функциями, а не subs. Выражение лямбда eventRaised = true
интерпретируется как булево выражение, а не как присваивание, то есть оценивается как ложное, а не устанавливается в true.
Подробнее о MSDN.
Я не думаю, что шаблон С# для тестирования событий, используемых в примере, может быть выполнен в VB.Net без введения другой функции, например.
<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
Ответ 2
Для тех, кто сейчас задает этот вопрос: поскольку Visual Basic 2010 (VB 10.0) анонимный Sub
работает, поэтому вы можете написать что-то вроде:
Sub() eventRaised = True
Ответ 3
Короче говоря, вы не можете сделать это в VB на данный момент (это в списке функций, рассмотренных для следующего выпуска). Вы должны использовать объявленный метод и оператор AddressOf.
У команды VB не было времени включать анонимных делегатов на этом языке (это то, что вы пытаетесь использовать, технически не лямбда-выражение).
Лямбда-выражения, которые они должны были реализовать, чтобы Linq мог работать. Анонимные делегаты не требуются ничем (но были бы весьма полезными). Я предполагаю, что они потратили больше времени на завершение таких вещей, как Linq To XML и XML litterals и интеграцию большего числа операторов запроса в синтаксис...