2015-08-27 8 views
6

Właśnie natknąłem się na sytuację, w której kolega napisał błąd i nie rozumieliśmy, dlaczego tak się stało, mimo że wiemy, jak to naprawić. Używam wyrażeń lamda od lat, ale jestem dużo bardziej doświadczony z C# niż VB i oczywiście mam fundamentalne niezrozumienie czegoś.Błąd spowodowany przez użycie funkcji zamiast podrzędnej w pojedynczym wierszu wyrażenia lambda

Poniższe obserwuje się w Visual Studio 2010 z .Net 3.5.

uprościłem to w dół do następnego prostego kodu testowego powielana podobny scenariusz:

Na formularzem systemu Windows umieścić następujące informacje, aby po prostu wykonać lambda a następnie wydrukować wartości obiektu badanego pole tekstowe:

Private Sub ExecuteAction(ByVal action As Action(Of TestClass)) 
    Dim testObj As New TestClass() 
    action(testObj) 
    TextBox1.Text = testObj.MyInteger 
End Sub 

Public Class TestClass 
    Public MyInteger As Integer 
End Class 

a następnie uruchamiam kod, aby wywołać go za pomocą lambda.

W poniższym przypadku wyświetlania w polu tekstowym jest 15 jak bym się spodziewał:

ExecuteAction(Sub(obj) obj.MyInteger = 15) 

w następującym przypadku wyjście jest również 15 jako spodziewałbym (to generuje ostrzeżenie, ponieważ nie zwraca wartości jest określona co rozumiem i jest w porządku, ponieważ robi to, co jest spodziewane):

ExecuteAction(Function(obj) 
       obj.MyInteger = 15 
       End Function) 

W poniższym przypadku wynik jest 0, a ja nie rozumiem dlaczego:

ExecuteAction(Function(obj) obj.MyInteger = 15) 

Dlaczego w ostatecznym scenariuszu wartość obiektu nie zmienia się na 15? Muszę zrozumieć tę różnicę między lambdami z funkcją pojedynczej linii a lambdami funkcji multi line, aby sprawdzić, czy muszę sprawdzić wszystkie nasze produkty pod kątem podobnych błędów. Kompiluje się dobrze i nie generuje ostrzeżeń, co czyni go niezwykle niebezpiecznym dla naszych zastosowań.

Próbowałem następujące czynności, aby sprawdzić, czy to sprawiło żadnej różnicy zmuszając wykonanie przed każdym niejawny powrót, ale tak się nie stało:

ExecuteAction(Function(obj) (obj.MyInteger = 15)) 

Odpowiedz

9

Różnica między wielu linii i pojedynczych funkcji jest to, że jeden zawiera instrukcja, a druga zawiera wyrażenie.

Gdy obj.MyInteger = 15 jest stwierdzeniem, to operator przypisania jest =. Gdy jest to wyrażenie, wówczas operator porównania jest =.

multi wersja linia swojej funkcji pojedynczej linii to:

ExecuteAction(Function(obj) 
    Return obj.MyInteger = 15 
End Function) 

To będzie porównanie wartości i zwraca wartość logiczną. Ponieważ oczekiwane jest Action(Of TestClass), nie ma wymogu co do typu zwracanej wartości, więc nie zauważysz, że zwraca wartość boolowską.

+0

dziękuję, to ma sens. Oczywiście bezpośrednia sytuacja nie może się zdarzyć w C#, ponieważ ma == dla porównania i = dla zadania, które mnie zdezorientowało. Upewnię się, że nasze standardy programowania zostaną zaktualizowane i wyślemy wyrok w sprawie sprawdzenia, jak prawdopodobne jest, że złapaliśmy nas gdzie indziej. Dzięki jeszcze raz. –