Verknüpfung zum Erstellen einer Liste einzelner Elemente in C #


134

Gibt es in C # eine Inline-Verknüpfung zum Instanziieren einer Liste <T> mit nur einem Element?

Ich mache gerade:

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

Wenn Sie diesen Code überall haben, verringert sich die Lesbarkeit. Ich habe überlegt, eine Dienstprogrammmethode wie diese zu verwenden:

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

Also könnte ich tun:

SingleItemList("title");

Gibt es einen kürzeren / saubereren Weg?

Vielen Dank.

Antworten:


245

Verwenden Sie einfach dies:

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

Sie können sogar die () Klammern weglassen:

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

Update: Das funktioniert natürlich auch für mehr als einen Eintrag:

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

5
Setzen Sie ein 1-Literal in die Klammern der ersten Option, damit der Speicher für genau einen Speicherplatz zugewiesen wird und nicht die Standardeinstellung 10
Joel Coehoorn

5
Der Standardwert ist 4, glaube ich: new List <string> {"Hello"} .Capacity == 4
Jon Skeet

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

Sehr ähnlich zu dem, was andere gepostet haben, außer dass sichergestellt wird, dass zunächst nur Platz für das einzelne Element zugewiesen wird.

Wenn Sie wissen, dass Sie später ein paar Dinge hinzufügen werden, ist dies natürlich keine gute Idee, aber dennoch einmal erwähnenswert.


Kapazität auf eins gesetzt. Ich habe auf dieser Seite für vier Antworten gestimmt, darunter beide von Jon Skeet, aber ich halte diese für die richtigste.
Der einsame Kodierer

28

Michaels Idee, Erweiterungsmethoden zu verwenden, führt zu etwas noch Einfacherem:

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

Sie könnten also Folgendes tun:

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

Ich bin mir nicht sicher, ob es mir gefällt oder nicht, wohlgemerkt ...


1
Ich bin mir auch nicht sicher, ob es mir gefällt: Ist das nicht eine "seltsame" Erweiterung des String-Typs (zum Beispiel)?
M4N

1
Ich habe es in Ihrem Buch noch nicht zu Erweiterungsmethoden geschafft, Jon :-) Das scheint irgendwie seltsam, aber ich mag die Nützlichkeit davon. Danke Martin und Jon.
Ryan Ische

2
@ Martin: Es ist eine seltsame Erweiterung von jedem Typ. Dies wird im Allgemeinen nicht empfohlen, ist jedoch eine interessante allgemeine Idee.
Jon Skeet

4
Es hat einige interne domänenspezifische Sprachverwendungen, insbesondere bei Werttypen. Nehmen wir zum Beispiel: clock.AlertUser.In (1.Minute) liest viel besser als clock.AlertUser (TimeSpan.FromMinutes (1));
Michael Meadows

17

Eine andere Antwort als meine frühere, basierend auf der Exposition gegenüber den Google Java-Sammlungen :

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

Dann:

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

Ich empfehle, das GJC zu überprüfen - es enthält viele interessante Dinge. (Persönlich würde ich das "Alpha" -Tag ignorieren - es ist nur die Open Source-Version, die "Alpha" ist und auf einer sehr stabilen und stark genutzten internen API basiert .)



7

Verwenden Sie eine Erweiterungsmethode mit Methodenverkettung.

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

Dies würde Sie dies tun lassen:

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

oder

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

Aktualisieren

Sie können jetzt Listeninitialisierer verwenden:

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

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


Vielleicht liegt das an neueren Versionen von C # seit 2009, aber ich finde new List<string> {"Yes"}es besser ...?
ErikE

@ErikE Laut Microsoft-Dokumentation ( msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx ) wurde dies in Visual Studio 2008 unterstützt Ich habe das damals überkompliziert. Aktualisierung.
Michael Meadows

7

Noch ein anderer Weg, gefunden auf "C # /. Net Little Wonders" (leider existiert die Seite nicht mehr):

Enumerable.Repeat("value",1).ToList()

Verwirrend aber klug.
PRMan

4

Für ein einzelnes in Java aufzählbares Element wäre es Collections.singleton ("string");

In c # wird dies effizienter sein als eine neue Liste:

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;
    }
}

Aber gibt es eine einfachere Möglichkeit, das Framework zu verwenden?


Das ist meiner Meinung nach die beste Antwort. Es ist ein sehr verbreitetes Muster, eine einzelne Artikelliste zu haben, um die Zuordnungsgröße zu verringern. Wenn Sie bereits nach einer Verknüpfung suchen, können Sie das Praktische mit dem Guten kombinieren.
Alex


2

Ich habe diese kleine Funktion:

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

Da es keinen konkreten Rückgabetyp vorschreibt, ist dieser so allgemein gehalten, dass ich ihn überall verwende. Ihr Code würde so aussehen

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

Aber natürlich erlaubt es auch

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

Ich verwende es oft, wenn ich ein Element an die Ausgabe einer LINQ-Anweisung anhängen / voranstellen muss. So fügen Sie einer Auswahlliste beispielsweise ein leeres Element hinzu:

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

Speichert ein paar ToList()und AddAussagen.

(Späte Antwort, aber ich bin auf diesen Oldie gestoßen und dachte, das könnte hilfreich sein)



2

Inspiriert von den anderen Antworten (und so kann ich es jederzeit abholen!), Aber mit Benennung / Stil, der an F # ausgerichtet ist (mit einer Standardfunktion singletonpro Datenstruktur *):

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

* außer für ResizeArraysich natürlich, daher diese Frage :)


In der Praxis ich eigentlich nennen Sie es Createmit anderen Helfern auszurichten Ich sehe wie Tuple.Create, Lazy.Create[2], LazyTask.Createetc:

namespace System.Collections.Generic
{
    public 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);
    }
}

Vielen Dank! Meine Lösung auch. Einige Dinge: (1) Ihre Listenimplementierung ist nicht öffentlich und kann daher nicht außerhalb der deklarierenden Assembly verwendet werden. (2) Wozu werden diese in den System-Namespace eingefügt?
Codure

@StephenRobinson Grund für das Einfügen der LazyErweiterung Systemist, dass sich Lazyselbst in System[befindet und daher Createin den Compleiton-Listen ohne a erscheinen würde using]. Es gibt nichts zu gewinnen, wenn man Leute in openeinen anderen Namespace zwingt ? Das andere privat zu machen war nicht beabsichtigt; behoben
Ruben Bartelink

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.