2009-12-30 15 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. Czy kopia jakiegośStruktu jest tworzona po utworzeniu lambda?
  2. Czy kopia jakiegośStruktu jest tworzona po powrocie Foo?
  3. Czy mogę sprawdzić, czy kopiowanie nie występuje? W C++ implementowałbym konstruktora kopiowania i drukowałam z niego.

Cytaty z normy zostaną docenione. Wszelkie odpowiednie artykuły online.Czy podczas przechwytywania wartości typu do lambda wykonywane jest kopiowanie?

Odpowiedz

7

Nie będzie kopii. Lambdas przechwytuje zmienne, a nie wartości.

Możesz użyć Reflectora, aby przyjrzeć się kodowi kompilacji: kompilator przeniesie zmienną "someStruct" do klasy pomocniczej.

private static void Foo() 
{ 
    DisplayClass locals = new DisplayClass(); 
    locals.someStruct = new SomeStruct { Num = 5 }; 
    action = new Action(locals.b__1); 
} 
private sealed class DisplayClass 
{ 
    // Fields 
    public SomeStruct someStruct; 

    // Methods 
    public void b__1() 
    { 
     Console.WriteLine(this.someStruct.Num); 
    } 
} 

struktury Kopiowanie nie spowoduje zdefiniowany przez użytkownika kodu do uruchomienia, tak naprawdę nie można sprawdzić to w ten sposób. W rzeczywistości kod zrobi kopię podczas przypisywania zmiennej "someStruct". Mógłby to zrobić nawet dla zmiennych lokalnych bez żadnych lambd.

6

Nie zostanie skopiowany, tworzy zamknięcie. Zasadniczo będzie enkapsulować strukturę w jednym obiekcie, zamiast tworzyć go na stosie.

Jeśli chcesz mieć pewność, że zawsze możesz użyć odbłyśnika, ale nie ma takiej potrzeby, zachowanie jest wyjaśnione na Raymond Chen blog.

+0

Jedynym problemem jest to, że nie możesz utworzyć konstruktora bez parametrów dla struktury. – Rory

+0

Opps, przepraszam za to – albertein

0

Nie, nie kopiuje, z tego samego powodu (kompilator tworzy klasę za kulisami, aby utrzymać wartość), że kopia innych typów wartości nie jest tworzona podczas przechwytywania zmiennej w lambda.

na przykład, jeśli nie:

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

lambda podziela 'i' z zakresu uznającej. to samo stanie się z twoją strukturą. możesz to zrobić jako test, aby udowodnić, że kopiowanie nie występuje.

Powiązane problemy