2015-01-21 21 views
5

Sono interessato a come viene implementata la variabile di default denominata uguale alla funzione.La variabile di ritorno predefinita della funzione è sempre allocata?

  • Sum è sempre assegnato anche se non lo sto utilizzando? (vedi case 1)
  • Se si sceglie un'altra variabile (Total in CASE 3), viene utilizzato invece di Sum?

I seguenti 3 casi equivalenti sono equivalenti anche quando compilati? O è superiore agli altri?

' EQUIVALENT CASES 

' CASE 1 
Function Sum(a As Integer, b As Integer) As Integer 
    Return a + b 
End Function 

' CASE 2 
Function Sum(a As Integer, b As Integer) As Integer 
    Sum = a + b 
End Function 

' CASE 3 
Function Sum(a As Integer, b As Integer) As Integer 
    Dim Total As Integer 
    Total = a + b 
    Return Total 
End Function 

Come ho letto da qualche parte, le funzioni di compilazione a meno di 32 byte vengono inserite in linea. Mi chiedo se in alcuni casi, potrei finire sopra o sotto il limite solo a causa della notazione scelta.

+0

Mi azzardo a indovinare che il compilatore rende tutti e tre di quelli la stessa cosa. Il caso 3 potrebbe "perdere" tempo creando la variabile però. – Keith

risposta

4

Ho rinominato le funzioni su Sum1, Sum2 e Sum3, rispettivamente, quindi le ho eseguite tramite LinqPad. Ecco il generato IL:

Sum1: 
IL_0000: ldarg.1  
IL_0001: ldarg.2  
IL_0002: add.ovf  
IL_0003: ret   

Sum2: 
IL_0000: ldarg.1  
IL_0001: ldarg.2  
IL_0002: add.ovf  
IL_0003: stloc.0  // Sum2 
IL_0004: ldloc.0  // Sum2 
IL_0005: ret   

Sum3: 
IL_0000: ldarg.1  
IL_0001: ldarg.2  
IL_0002: add.ovf  
IL_0003: stloc.1  // Total 
IL_0004: ldloc.1  // Total 
IL_0005: ret   

Sembra che Sum2 e Sum3 abbiano lo stesso IL. Sum1 sembra essere più efficiente poiché mette il risultato dell'operatore direttamente sulla pila. Gli altri devono estrarre il risultato dallo stack nella variabile locale e quindi reinserirlo nello stack!

+0

Molto interessante vedere che il compilatore non li ottimizza, specialmente il caso 2. Sono contento di usare sempre il caso 1, risparmiando quei nanosecondi! : P – Keith

+0

@Keith - Questo IL proviene da LinqPad. È possibile che, quando compilato da VS in modalità Release o JITted, possa essere ottimizzato come suggerito. –

+0

@Keith - potrebbe non riguardare solo la creazione di variabili, ma anche l'inlining. Il corpo della fucilazione è inserito in linea o c'è una chiamata normale fatta mettendo i parametri in pila e tutta quella roba ... – miroxlav

2

Non sono un esperto VB.NET, ma so qualcosa su C#. In C#, questo tipo di codice non è permesso. Si dovrebbe sempre return un valore, altrimenti il ​​codice non verrà compilato.

immagino VB.NET aggira questo qualcosa di simile in C#:

T Sum = default(T); 

... 

return Sum; 

Il valore predefinito è il valore di Sum, che nel caso di un int è 0.

In base a questa logica, la variabile viene allocata, per i tipi di riferimento, ciò significa che non ci sarà alcuna allocazione, dal momento che sono predefiniti su null.

Guardando il IL:

.method public static int32 Test() cil managed 
{ 
    // Code size  3 (0x3) 
    .maxstack 1 
    .locals init ([0] int32 Test) 
    IL_0000: nop 
    IL_0001: ldloc.0 
    IL_0002: ret 
} // end of method Module1::Test 

da questo Function:

Function Test() As Integer 

End Function 

Si vedrà init, che inizializza una variabile (alloca) e ldloc, che è una chiamata per ottenere il valore di una variabile, quindi, deve essere assegnato.

+1

Lo so. Questo è il motivo per cui ho taggato questa domanda ** vb.net **, non solo **. Net ** o ** C# **. – miroxlav

+0

Cosa intendi? Cosa sai? –

+1

Ho commentato quando la risposta riguardava solo C#. Questo è il motivo per cui inizialmente lo ho downvoted. Sarei felice se potessimo rimanere in VB perché i compilatori C# e VB potrebbero essere completamente diversi in merito all'approccio in questi casi. Inoltre, C# non supporta 'CASE 2'. Se puoi, rimuovi la parte C# della risposta. – miroxlav

Problemi correlati