2013-07-25 11 views
11

Jaki jest najlepszy sposób utworzenia listy z dowolną liczbą wystąpień tego samego obiektu? tj. czy istnieje bardziej kompaktowy lub skuteczny sposób na wykonanie następujących czynności?Tworzenie listy wypełnionej nowymi instancjami obiektu

static List<MyObj> MyObjs = Enumerable.Range(0, 100) 
    .Select(i => new MyObj()) 
    .ToList(); 

(Enumerable.Repeat dałby mi dziesięć odwołania do tego samego obiektu, więc nie sądzę, że to działa.)

+7

nie widzę żadnych problemów z obecnego podejścia ... – Brian

+0

Nie mówię, że nie ma problemu .. To po prostu wygląda jak włamanie. – Arithmomaniac

+2

"to po prostu czuć się jak hack". Dlaczego, wcale! To bije pętlę 'for' w dół :-) – dasblinkenlight

Odpowiedz

8

Nie byłoby to trudne do wdrożenia jako iterator:

IEnumerable<T> CreateItems<T> (int count) where T : new() { 
    return CreateItems(count,() => new T()); 
} 

IEnumerable<T> CreateItems<T> (int count, Func<T> creator) { 
    for (int i = 0; i < count; i++) { 
     yield return creator(); 
    } 
} 
3

Wydaje się, że odpowiedź brzmi „nie”. Dziękuję wszystkim!

6

Edytowany w celu odzwierciedlenia, że ​​ta metoda nie działa pod.

Byłem ciekawy twojego komentarza na temat Enumerable.Repeat, więc spróbowałem.

List<object> myList = Enumerable.Repeat(new object(), 100).ToList(); 

Potwierdziłem, że wszystkie mają takie same odniesienia jak wspomniany PO.

+2

Nadpisujesz wystąpienia, wykonując 'myList [i] = ...'. Utwórz klasę Foo, korzystając z paska właściwości, a następnie zmień pasek, zobaczysz, że zmienia się dla każdego indeksu. – cadrell0

+0

@ cadrell0 dziękuję za komentarz. Masz rację - rzuciłem się tam. Zostawię tutaj swoją odpowiedź jedynie jako lekcję dla kogoś innego na temat tego, czego nie robić. – Gray

2

Nie jestem pewien, co jest nie tak z pętlą for w tym przypadku. Przynajmniej możemy przewidzieć pojemność listy. To może nie być ważne dla 100 obiektów, ale rozmiar jest arbitralny.

public class MyClass 
{ 
    static int Capacity = 100; 
    static List<MyObj> MyObjs = new List<MyObj>(Capacity); 

    static MyClass() { 
     for(var i = 0; i < Capacity; i++) { 
      MyObjs.Add(new MyObj()); 
     } 
    } 
} 
+1

Użycie 'ToList' używa' List (IEnumerable items) 'konstruktora' List ', co moim zdaniem jest trochę szybsze niż wywołanie' Add' dla każdego elementu. Jest przynajmniej taki sam. 'Range' używa wewnętrznie pętli' for'. Twoje rozwiązanie to co najmniej ta sama wydajność, ale więcej kodu. – cadrell0

+0

Metoda .Select musi koniecznie utworzyć nową wyliczenie, ponieważ typ zmienił się z int na MyObj. Musi także wywołać anonimową metodę 100 razy i ostatecznie przekształcić to wszystko w listę . – B2K

+1

http://msdn.microsoft.com/en-us/library/vstudio/9k7k7cf0.aspx Zarówno zakres, jak i wybór korzystają z 'zwrotu plonów'. Ponieważ wykonanie jest odłożone do tego stopnia, że ​​wywoływane jest 'ToList', wyniki są wyliczane tylko raz, co dzieje się podczas budowania listy. – cadrell0