2009-01-20 31 views
93

W języku C# znajduje się wbudowany skrót do utworzenia instancji z jedną tylko pozycją.Skrót do tworzenia listy pojedynczych elementów w języku C#

Jestem obecnie robi:

new List<string>(new string[] { "title" })) 

Mając ten kod wszędzie zmniejsza czytelność. Myślałem o użyciu metody narzędzie tak:

public static List<T> SingleItemList<T>(T value) 
{ 
    return (new List<T>(new T[] { value })); 
} 

Więc mogę zrobić:

SingleItemList("title"); 

Czy istnieje krócej/czystszy sposób?

Dzięki.

Odpowiedz

168

Wystarczy użyć tego:

List<string> list = new List<string>() { "single value" }; 

Można nawet pominąć() szelki:

List<string> list = new List<string> { "single value" }; 

Aktualizacja: Oczywiście działa to również dla więcej niż jednego wpisu:

List<string> list = new List<string> { "value1", "value2", ... }; 
+4

umieść 1 literał w nawiasach pierwszej opcji, więc zamiast tego przypisuje się miejsce na dokładnie jedną spację, a nie domyślną. 10 –

+4

Domyślnie kończy się 4, myślę: nowa lista {"Cześć"} .Przydatność == 4 –

7

Użyj metody rozszerzającej z łączeniem metod.

public static List<T> WithItems(this List<T> list, params T[] items) 
{ 
    list.AddRange(items); 
    return list; 
} 

Byłoby to niech to zrobić:

List<string> strings = new List<string>().WithItems("Yes"); 

lub

List<string> strings = new List<string>().WithItems("Yes", "No", "Maybe So"); 

Aktualizacja

Można teraz używać lista inicjatorów:

var strings = new List<string> { "This", "That", "The Other" }; 

Zobacz http://msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx

+0

Może to ze względu na nowsze wersje C# od 2009 roku, ale uważam 'nową listę {” Tak "}" by być lepszym ...? – ErikE

+0

@ErikE Zgodnie z dokumentacją Microsoft (http://msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx) było to obsługiwane w Visual Studio 2008. Nie pamiętam, że daleko z powrotem, aby powiedzieć definitywnie, czy w tym czasie zbytnio to skomplikowałem. Aktualizacja. –

1

Można również zrobić

new List<string>() { "string here" }; 
16

pomysł Michaela z użyciem metod rozszerzenie prowadzi do czegoś jeszcze prostszy:

public static List<T> InList(this T item) 
{ 
    return new List<T> { item }; 
} 

Więc można zrobić:

List<string> foo = "Hello".InList(); 

Nie jestem pewien, czy I podoba ci się to, czy nie, zwróćcie uwagę ...

+0

Nie jestem również pewien, czy mi się podoba: czy nie jest to "dziwne" rozszerzenie typu łańcucha (na przykład)? – M4N

+1

Nie wprowadziłem jeszcze do metod rozszerzenia w twojej książce, Jon :-) To wydaje się dziwne, ale podoba mi się jego użyteczność. Dzięki Martin i Jon. –

+2

@Martin: To dziwne rozszerzenie * every * type. Zasadniczo jest to odradzane, ale jest to interesujący ogólny pomysł. –

1

Chciałbym po prostu zrobić

var list = new List<string> { "hello" }; 
11

inną odpowiedź na moje wcześniej, na podstawie ekspozycji na Google Java Collections:

public static class Lists 
{ 
    public static List<T> Of<T>(T item) 
    { 
     return new List<T> { item }; 
    } 
} 

wówczas:

List<string> x = Lists.Of("Hello"); 

Radzę sprawdzania się GJC - ma wiele ciekawych rzeczy. (Osobiście zignorowałbym tag "alpha" - to tylko t on w wersji open source, która jest „alfa” i jest oparta na bardzo stabilnym i intensywnie wykorzystywanym API wewnętrznego.)

30
var list = new List<string>(1) { "hello" }; 

Bardzo podobny do tego, co inni napisali, oprócz tego, że dba tylko przydzielić miejsca dla singla element początkowo.

Oczywiście, jeśli wiesz, że dodasz kilka rzeczy później, może to nie być dobry pomysł, ale warto go wspomnieć tylko raz.

+0

Pojemność ustawiona na jeden. Głosowałem za czterema odpowiedziami na tej stronie, w tym obaj z Jonem Skeetem, ale uważam, że ten jest najbardziej poprawny. –

0

Dla pojedynczego elementu wyliczalnego w java będzie to Collections.singleton ("ciąg znaków");

w C# to będzie bardziej efektywne niż nową listę:

public class SingleEnumerator<T> : IEnumerable<T> 
{ 
    private readonly T m_Value; 

    public SingleEnumerator(T value) 
    { 
     m_Value = value; 
    } 

    public IEnumerator<T> GetEnumerator() 
    { 
     yield return m_Value; 
    } 

    IEnumerator IEnumerable.GetEnumerator() 
    { 
     yield return m_Value; 
    } 
} 

ale czy istnieje prostszy sposób, korzystając z ram?

2

Mam ten mały funkcję:

public static class CoreUtil 
{  
    public static IEnumerable<T> ToEnumerable<T>(params T[] items) 
    { 
     return items; 
    } 
} 

Ponieważ nie określa konkretny typ zwracany jest to tak ogólne, że mogę używać go w każdym miejscu. Twój kod będzie wyglądać

CoreUtil.ToEnumerable("title").ToList(); 

Ale oczywiście pozwala również

CoreUtil.ToEnumerable("title1", "title2", "title3").ToArray(); 

często używam go kiedy mam do dołączania/prepend jeden element do wyjścia oświadczenie LINQ. Na przykład, aby dodać pustą pozycję na liście wyboru:

CoreUtil.ToEnumerable("").Concat(context.TrialTypes.Select(t => t.Name)) 

Zapisuje kilka ToList() i Add oświadczenia.

(Late odpowiedź, ale natknąłem się na tym, że ten staruszek i może być pomocne)

1

Zainspirowany innych odpowiedzi (a więc mogę go podnieść, kiedy go potrzebuję!), Ale z nazewnictwa/stylu zgodnym z F # (który ma standardową singleton funkcję za struktury danych *):

namespace System.Collections.Generic 
{ 
    public static class List 
    { 
     public static List<T> Singleton<T>(T value) => new List<T>(1) { value }; 
    } 
} 

* z wyjątkiem ResizeArray sama oczywiście, stąd to pytanie :)


w praktyce ja faktycznie imię to Create do zrównania z innymi pomocnikami zdefiniować takie jak Tuple.Create, Lazy.Create [2], LazyTask.Create etc:

namespace System.Collections.Generic 
{ 
    static class List 
    { 
     public static List<T> Create<T>(T value) => new List<T>(1) { value }; 
    } 
} 

[2]

namespace System 
{ 
    public static class Lazy 
    { 
     public static Lazy<T> Create<T>(Func<T> factory) => new Lazy<T>(factory); 
    } 
} 
+0

Dzięki! Moje rozwiązanie również. Kilka rzeczy: (1) implementacja listy nie jest publiczna, więc nie można jej używać poza deklarowanym zbiorem, oraz (2) jaki jest cel wrzucania jej do przestrzeni nazw Systemu? –

+0

@StephenRobinson powodem umieszczenia rozszerzenia 'Lazy' w' System' jest to, że 'Lazy' sam jest w' System' [i stąd 'Create' pojawi się na liście compleiton bez' use']. Nie ma nic do zyskania, zmuszając ludzi do "otwarcia" przestrzeni nazw diff? Sprawienie, by druga rzecz była prywatna, nie było zamierzone; naprawiono –

1
new[] { "item" }.ToList(); 

To krócej niż

new List<string> { "item" }; 

i nie trzeba określić typ.

0

Spróbuj var

var s = new List<string> { "a", "bk", "ca", "d" }; 
Powiązane problemy