Raccourci pour créer une liste d'éléments uniques en C #


134

En C #, existe-t-il un raccourci en ligne pour instancier un List <T> avec un seul élément.

Je fais actuellement:

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

Avoir ce code partout réduit la lisibilité. J'ai pensé à utiliser une méthode utilitaire comme celle-ci:

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

Donc je pourrais faire:

SingleItemList("title");

Existe-t-il un moyen plus court / plus propre?

Merci.

Réponses:


245

Utilisez simplement ceci:

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

Vous pouvez même omettre les accolades ():

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

Mise à jour: bien sûr, cela fonctionne également pour plus d'une entrée:

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

5
mettre un 1 littéral entre parenthèses de la première option, de sorte que le stockage pour exactement un espace soit alloué plutôt que le 10 par défaut
Joel Coehoorn

5
La valeur par défaut finit par être 4, je crois: nouvelle liste <string> {"Hello"} .Capacity == 4
Jon Skeet

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

Très similaire à ce que d'autres ont publié, sauf que cela garantit d'allouer uniquement de l'espace pour l'élément unique au départ.

Bien sûr, si vous savez que vous allez ajouter un tas de choses plus tard, ce n'est peut-être pas une bonne idée, mais cela vaut la peine d'être mentionné une fois.


Capacité définie à un. J'ai voté pour quatre réponses sur cette page, y compris celles de Jon Skeet, mais je considère que celle-ci est la plus correcte.
The Lonely Coder

28

L'idée de Michael d'utiliser des méthodes d'extension conduit à quelque chose d'encore plus simple:

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

Vous pouvez donc faire ceci:

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

Je ne sais pas si cela me plait ou non, remarquez ...


1
Je ne suis pas sûr non plus de l'aimer: n'est-ce pas une extension "étrange" du type chaîne (par exemple)?
M4N

1
Je n'ai pas encore atteint les méthodes d'extension dans votre livre, Jon :-) Cela semble un peu étrange, mais j'aime son utilité. Merci Martin et Jon.
Ryan Ische

2
@Martin: C'est une étrange extension de chaque type. C'est généralement déconseillé, mais c'est une idée générale intéressante.
Jon Skeet le

4
Il a des utilisations de langage spécifiques à un domaine interne, en particulier avec les types valeur. Prenons par exemple: clock.AlertUser.In (1.Minute) lit beaucoup mieux que clock.AlertUser (TimeSpan.FromMinutes (1));
Michael Meadows

17

Une réponse différente de la précédente, basée sur l'exposition aux collections Google Java :

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

Ensuite:

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

Je conseille de vérifier le GJC - il contient beaucoup de choses intéressantes. (Personnellement, j'ignorerais la balise "alpha" - c'est seulement la version open source qui est "alpha" et elle est basée sur une API interne très stable et très utilisée .)


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

C'est plus court que

new List<string> { "item" };

et vous n'avez pas à spécifier le type.


7

Utilisez une méthode d'extension avec chaînage de méthodes.

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

Cela vous permettrait de faire ceci:

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

ou

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

Mettre à jour

Vous pouvez maintenant utiliser des initialiseurs de liste:

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

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


Peut-être que cela est dû aux nouvelles versions de C # depuis 2009, mais je trouve que new List<string> {"Yes"}c'est mieux ...?
ErikE

@ErikE Selon la documentation Microsoft ( msdn.microsoft.com/en-us/library/bb384062(v=vs.90).aspx ), cela a été pris en charge dans Visual Studio 2008. Je ne me souviens pas si loin pour dire définitivement si J'ai trop compliqué cela à l'époque. Mise à jour.
Michael Meadows

7

Encore une autre façon, trouvée sur "C # /. Net Little Wonders" (malheureusement, le site n'existe plus):

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

Confus mais intelligent.
PRMan du

4

Pour un seul élément énumérable en java, ce serait Collections.singleton ("string");

En c #, cela va être plus efficace qu'une nouvelle 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;
    }
}

mais y a-t-il un moyen plus simple d'utiliser le framework?


C'est en fait la meilleure réponse à mon avis. Il est très courant d'avoir une seule liste d'éléments, pour réduire la taille de l'allocation. Si vous êtes déjà à la recherche d'un raccourci, vous pouvez aussi bien combiner le pratique avec le bien.
Alex


2

J'ai cette petite fonction:

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

Puisqu'il ne prescrit pas de type de retour concret, c'est tellement générique que je l'utilise partout. Votre code ressemblerait à

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

Mais bien sûr, cela permet aussi

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

Je l'utilise souvent lorsque je dois ajouter / ajouter un élément à la sortie d'une instruction LINQ. Par exemple pour ajouter un élément vide à une liste de sélection:

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

Enregistre quelques ToList()et Adddéclarations.

(Réponse tardive, mais je suis tombé sur cet ancien et j'ai pensé que cela pourrait être utile)



2

Inspiré par les autres réponses (et donc je peux le récupérer quand j'en ai besoin!), Mais avec un nom / style aligné sur F # (qui a une singletonfonction standard par structure de données *):

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

* sauf pour ResizeArraylui-même bien sûr, d'où cette question :)


Dans la pratique , je fait le nomme Createà aligner avec d' autres aides telles que je définis 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);
    }
}

Merci! Ma solution aussi. Deux choses: (1) l'implémentation de votre liste n'est pas publique, donc elle ne peut pas être utilisée en dehors de l'assembly déclarant, et (2) quel est le but de les insérer dans l'espace de noms System?
Codure le

La raison pour laquelle @StephenRobinson a mis l' Lazyextension Systemest qu'elle est Lazyelle - même dans System[et Createapparaîtrait donc dans les listes de compilation sans using]. Il n'y a rien à gagner à forcer les gens à openun espace de noms diff? Rendre l'autre chose privée n'était pas intentionnel; corrigé
Ruben Bartelink

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.