2013-03-11 15 views
6

W specyficzny, jeśli powiem:jaki sposób stosowanie kompilator „powrót połów” zbudować klasę

public static IEnumerable<String> Data() 
    { 
     String connectionString = "..."; 
     using (SqlConnection connection = new SqlConnection(connectionString)) 
     { 
      connection.Open(); 

      IDataReader reader = new SqlCommand("", connection).ExecuteReader(); 

      while (reader.Read()) 
       yield return String.Format("Have a beer {0} {1}!", reader["First_Name"], reader["Last_Name"]); 

      connection.Close(); 
     } 
    } 

jaki sposób kompilator iść o generowanie konkretną klasę enumerable z tego?

+2

To czarna magia, mówię wam. –

Odpowiedz

8

To buduje maszynę stanu, w zasadzie:

  • tworzy prywatną klasę zagnieżdżonych ze zmiennych instancji odpowiadających lokalnych zmiennych w swojej metody i zmienną state śledzić gdzie to musi
  • stan maszyny realizuje IEnumerable<T> i IEnumerator<T> - metoda MoveNext() dostaje się do prawej odrobiną logiki (na podstawie state) i ustawia zmienną instancji śledzić ostatniej-dały wartości (właściwość Current)
  • Kompilator tworzy „szkielet” metody o takiej samej sygnaturze jak oryginału, który tworzy instancję machiny państwowej

Zobacz my article on the topic więcej szczegółów. Zauważ również, że asynchroniczne/oczekiwane w C# 5 jest zbudowany z wielu tych samych pomysłów (choć istnieją różne różnice w implementacji).

+0

Możesz chcieć zaadresować 'return yield' w' using'? – manojlds

+0

@manojlds: Naprawdę nic specjalnego. Maszyna stanu jest budowana po tym, jak 'using' jest podzielone na składniki inicjujące i czyszczące. Wyjątek obsługi "finally" w ogóle (nie tylko 'using') są przenoszone do metody" Dispose "wygenerowanej klasy. –

+0

@BenVoigt - OP mówi konkretny przykład, a zysk zwrotu w użyciu, specjalne lub nie, wydawało się warte wspomnienia. – manojlds

Powiązane problemy