Servy poprawnie odpowiedział na to pytanie - pytanie odpowiedziałeś sobie w komentarzu:
zdałem sobie sprawę, że od zwracany typ jest interfejs, byłoby dostać zapakowane tak, zgadza się?
Dobrze. Twoje pytanie uzupełniające:
nie można zmienić metody zwracania jawnie wpisanego modułu wyliczającego (jak robi to List<T>
)?
Więc Chodzi o to, że użytkownik pisze:
IEnumerable<int> Blah() ...
i kompilator faktycznie generuje metodę, która zwraca BlahEnumerable
który jest struct, który implementuje IEnumerable<int>
, ale z odpowiednim GetEnumerator
etc metody i właściwości które pozwalają na "dopasowanie do wzorca" funkcji foreach
, aby usunąć bokser.
Chociaż jest to prawdopodobny pomysł, istnieją poważne trudności, gdy zaczynasz kłamać na temat metody zwrotu metody. Szczególnie gdy kłamstwo polega na zmianie, czy metoda zwraca struct lub typ referencyjny. Pomyśl o wszystkich błędach:
Załóżmy, że metoda jest wirtualna. Jak można go przesłonić? Typ zwracanej metody zastępowania wirtualnego musi być dokładnie zgodny z metodą zastępowaną. (I podobnie dla: metoda zastępuje inną metodę, metoda implementuje metodę interfejsu itd.)
Załóżmy, że metoda została wprowadzona do delegata Func<IEnumerable<int>>
. Func<T>
jest kowariantny w T
, ale kowariancja dotyczy tylko argumentów typu referencyjnego.Kod wygląda tak, jakby zwracał wartość IEnumerable<T>
, ale w rzeczywistości zwracany jest typ wartości, który nie jest zgodny z kowariancyjnie z IEnumerable<T>
, a tylko zgodny z.
Załóżmy, że mamy void M<T>(T t) where T : class
i dzwonimy pod numer M(Blah())
. Spodziewamy się wydedukować, że T
to IEnumerable<int>
, który przechodzi test sprawdzania ograniczeń, ale typ struktury ma wartość , a nie.
I tak dalej. Szybko kończysz w odcinku Three's Company (chłopiec, z którym się tu umawiam), gdzie małe kłamstwo kończy się ogromną katastrofą. Wszystko po to, aby zaoszczędzić niewielką ilość ciśnienia w zbiorniku. Nie jest tego warte.
Zauważam jednak, że implementacja stworzona przez kompilator powoduje, żeoszczędza na ciśnieniu zbierania w jeden interesujący sposób. najpierw czas czas, który jest wywoływany na zwróconych wyliczalnych, przeliczalnych zwojów sam w sobie do modułu wyliczającego. Drugi raz oczywiście stan jest inny, więc przydziela nowy obiekt. Ponieważ prawdopodobny scenariusz 99,99% jest taki, że dana sekwencja jest wyliczana dokładnie raz, jest to duża oszczędność na presję gromadzenia danych.
Właśnie zdałem sobie sprawę, że ponieważ typem zwracanym jest interfejs ('IEnumerable' lub' IEnumerator'), to i tak będzie on (http://stackoverflow.com/questions/3032750/), czy to prawda? W takim przypadku nie można zmienić metody zwracania jawnie wpisanego modułu wyliczającego (np. [List] (https://msdn.microsoft.com/en-us/library/b0yss765 (v = vs.110). aspx))? Ponieważ implementuje interfejsy, wszystkie odwołania do kodu powinny być zachowane. (IIRC, działa to, ponieważ 'foreach' jest [wykrywany przez wzorzec] (https://blogs.msdn.microsoft.com/ericlippert/2011/06/30/following-the-pattern/)). –
Lazlo