2009-12-30 8 views
7
struct SomeStruct 
{ 
    public int Num { get; set; } 
} 

class Program 
{ 
    static Action action; 

    static void Foo() 
    { 
     SomeStruct someStruct = new SomeStruct { Num = 5 }; 
     action =() => Console.WriteLine(someStruct.Num); 
    } 

    static void Main() 
    { 
     Foo(); 
     action.Invoke(); 
    } 
} 
  1. è una copia di someStruct creato quando viene creato il lambda?
  2. È una copia di someStruct creata quando viene restituito Foo?
  3. Posso verificare che la copia non si verifica? In C++ implementerei il costruttore di copie e stamperei al suo interno.

Le citazioni dallo standard saranno apprezzate. Qualsiasi articolo online pertinente pure.La copia viene eseguita quando si acquisisce un tipo di valore in una lambda?

risposta

7

Non ci saranno copie. Lambdas cattura le variabili, non i valori.

È possibile utilizzare Reflector per esaminare il codice di compilazione: il compilatore sposta la variabile "someStruct" in una classe helper.

La copia delle strutture non causerà mai l'esecuzione del codice definito dall'utente, quindi non è possibile controllarlo in questo modo. In realtà, il codice eseguirà una copia durante l'assegnazione alla variabile "someStruct". Lo farebbe anche per le variabili locali senza alcun lambda.

6

Non verrà copiato, crea una chiusura. Fondamentalmente incapsulerà la struttura in un oggetto invece di crearlo sullo stack.

Se si vuole essere sicuri di poter utilizzare sempre il riflettore, ma non è necessario, il comportamento è spiegato su Raymond Chen blog.

+0

L'unico problema è che non è possibile creare un costruttore senza parametri per una struttura. – Rory

+0

Opps, mi dispiace per quello – albertein

0

No, non copia, per lo stesso motivo (il compilatore crea una classe dietro le quinte per mantenere il valore) che non viene creata una copia di altri tipi di valore quando si cattura una variabile in una lambda.

per esempio, se si fa:

int i = 7; 
Action a =() => Console.WriteLine("lambda i=" + i); 
i++; 
a(); //prints 8 
Console.WriteLine("main i=" + i); //prints 8 

lambda condivide la 'i' con lo scopo dichiarato. la stessa cosa accadrà con la tua struttura. puoi farlo come test per dimostrare che la copia non si verifica.

3

Vedere The implementation of anonymous methods in C# and its consequences (part 1). Il tuo codice è in realtà qualcosa del tipo:

class SomeHiddenClass { 
    SomeStruct someStruct; 
    someHiddenMethod() { 
     Console.WriteLine(someStruct.Num); 
    } 
    } 

    SomeHiddenClass someHiddenVar = new SomeHiddenClass(); 
    someHiddenVar.someStruct.Num = 5; 
    action = someHiddenVar.someHiddenMethod; 
+0

oops, hehe. +1 btw. – Will

Problemi correlati