2015-08-27 2 views
6

Ich bin gerade auf eine Situation gestoßen, in der ein Kollege einen Fehler geschrieben hat und wir nicht verstanden haben, warum es passiert ist, obwohl wir wissen, wie wir ihn beheben können. Ich benutze seit Jahren Lamda-Ausdrücke, bin aber viel erfahrener mit C# als VB und habe offensichtlich ein fundamentales Missverständnis von etwas.Fehler durch Verwendung von Funktion anstelle von sub in einzeiliger Lambda-Ausdruck

Folgendes wird in Visual Studio 2010 mit .Net 3.5 beobachtet.

Ich habe dies auf die folgenden einfachen Testcode vereinfacht unten, die ein ähnliches Szenario wiedergegeben:

in einem Windows Form ich folgendes setzen, um einfach eine Lambda ausführen und dann den Wert eines Testobjekts drucken zu ein Textfeld:

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 

und dann ich einige Code ausführen, um es mit einem Lambda aufzurufen.

Im folgenden Fall ist der Ausgang in der Textbox 15 ist, wie ich erwarten würde:

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

Im folgenden Fall ist die Ausgabe auch 15 als ich erwarten würde (es hat eine Warnung, weil kein Rückgabewert erzeugen spezifiziert ist, die ich verstehe und ist in Ordnung, weil es das tut, was zu erwarten ist):

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

im folgenden Fall ist der Ausgang 0 und ich verstehe nicht, warum:

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

Warum ändert sich der Wert des Objekts im letzten Szenario nicht auf 15? Ich muss diesen Unterschied zwischen Single-Line-Funktion Lambdas und Multi-Line-Funktion Lambdas verstehen, um zu sehen, ob ich über alle unsere Produkte für ähnliche Bugs überprüfen muss. Es kompiliert gut und erzeugt keine Warnungen, die es extrem gefährlich für unsere Zwecke machen.

ich folgend versucht zu sehen, ob es einen Unterschied, die Ausführung, bevor eine implizite Rückkehr erzwingen gemacht, aber es hat nicht:

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

Antwort

9

Der Unterschied zwischen der Multi-Line und den einzelnen Linienfunktionen ist, dass ein enthält eine Anweisung und die andere enthält einen Ausdruck.

Wenn obj.MyInteger = 15 eine Anweisung ist, dann ist = der Zuweisungsoperator. Wenn es ein Ausdruck ist, ist = der Vergleichsoperator.

Die Multi-Line-Version Ihrer Single-Line-Funktion ist:

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

Diese Werte vergleichen und einen Booleschen Wert zurück. Da ein Action(Of TestClass) erwartet wird, gibt es keine Anforderung für den Typ des Rückgabewerts, so dass Sie nicht bemerken, dass es einen booleschen Wert zurückgibt.

+0

danke, das macht Sinn. Offensichtlich konnte die direkte Situation in C# nicht passieren, weil es == zum Vergleich und = zur Zuweisung hat, was mich verwirrte. Ich werde dafür sorgen, dass unsere Programmierungsstandards aktualisiert werden, und wir werden prüfen, wie wahrscheinlich es ist, dass uns das an anderer Stelle erwischt hat. Danke noch einmal. –

Verwandte Themen