2015-08-27 10 views
6

Mi sono appena imbattuto in una situazione in cui un collega ha scritto un bug e non abbiamo capito perché è successo nonostante il fatto che sappiamo come risolverlo. Uso le espressioni lamda da anni ma ho molta più esperienza con C# rispetto a VB e ovviamente ho un fondamentale fraintendimento di qualcosa.Bug causato dall'uso della funzione invece della sub linea singola espressione lambda

Quanto segue si osserva in Visual Studio 2010 con .Net 3.5.

Ho semplificato questo giù al seguente codice semplice test che riproduce uno scenario simile:

Su un Windows Form ho messo il seguente, per eseguire semplicemente un lambda e quindi stampare il valore di un oggetto di prova per una casella di testo:

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 

e quindi eseguo un codice per chiamarlo utilizzando un lambda.

Nel seguente caso l'uscita nella casella di testo è di 15 come mi sarei aspettato:

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

Nel seguente caso l'uscita è anche 15 come ci si aspetta (lo fa generare un avviso perché nessun valore di ritorno è specificato che capisco e va bene perché fa quello che ci si aspetta):

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

Nel seguente caso l'uscita è 0 e non capisco il motivo per cui:

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

Perché nello scenario finale il valore dell'oggetto non cambia in 15? Ho bisogno di capire questa differenza tra lambdas funzione singola linea e lambda funzione multi linea per vedere se ho bisogno di controllare attraverso tutti i nostri prodotti per bug simili. Compila bene e non genera avvisi che lo rendono estremamente pericoloso per i nostri usi.

Ho provato quanto segue per vedere se facesse differenza costringendo l'esecuzione prima di qualsiasi ritorno implicito ma no:

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

risposta

9

La differenza tra la linea Multi e le funzioni di linea singola è che uno contiene un dichiarazione e l'altra contiene un'espressione.

Quando obj.MyInteger = 15 è un'istruzione, = è l'operatore di assegnazione. Quando è un'espressione, = è l'operatore di confronto.

La versione multi linea della funzione singola riga è:

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

Ciò confrontare i valori e restituire un valore booleano. Poiché è previsto un Action(Of TestClass), non è richiesto il tipo del valore restituito, quindi non si nota che restituisce un valore booleano.

+0

grazie, ha senso. Ovviamente la situazione diretta non può accadere in C# perché ha == per il confronto e = per l'incarico che mi ha confuso. Mi assicurerò che i nostri standard di programmazione siano aggiornati e facciano una valutazione per verificare quanto è probabile che questo ci abbia catturato altrove. Grazie ancora. –

Problemi correlati