web-dev-qa-db-fra.com

Existe-t-il un singleton "Liste vide" en C #?

En C # j'utilise un peu LINQ et IEnumerable. Et tout va bien (ou du moins surtout).

Cependant, dans de nombreux cas, je constate que j'ai besoin d'un IEnumerable<X> Vide par défaut. Autrement dit, je voudrais

for (var x in xs) { ... }

de travailler sans avoir besoin d'un contrôle nul. Maintenant, c'est ce que je fais actuellement, en fonction du contexte plus large:

var xs = f() ?? new X[0];              // when xs is assigned, sometimes
for (var x in xs ?? new X[0]) { ... }  // inline, sometimes

Maintenant, alors que ce qui précède est parfaitement bien pour moi - c'est-à-dire, s'il y a une "surcharge supplémentaire" avec la création de l'objet tableau I ne s'en soucie pas - Je me demandais:

Existe-t-il un singleton "vide immuable IEnumerable/IList" dans C # /. NET? (Et, même si ce n'est pas le cas, existe-t-il une "meilleure" façon de gérer le cas décrit ci-dessus?)

Java a Collections.EMPTY_LIST singleton immuable - "bien typé" via Collections.emptyList<T>() - qui remplit cette fonction, bien que je ne sois pas sûr si un concept similaire pourrait même fonctionner en C # parce que les génériques sont traités différemment.

Merci.

64
user166390

Vous recherchez Enumerable.Empty<int>();

Dans d'autres nouvelles, la liste vide Java Java est nulle parce que l'interface List expose des méthodes pour ajouter des éléments à la liste qui lèvent des exceptions.

82
Stilgar

Enumerable.Empty<T>() est exactement cela.

50
Jon

Je pense que vous cherchez Enumerable.Empty<T>() .

Le singleton de liste vide n'a pas beaucoup de sens, car les listes sont souvent modifiables.

18
svick

Je pense que l'ajout d'une méthode d'extension est une alternative propre grâce à leur capacité à gérer les valeurs nulles - quelque chose comme:

  public static IEnumerable<T> EmptyIfNull<T>(this IEnumerable<T> list)
  {
    return list ?? Enumerable.Empty<T>();
  }

  foreach(var x in xs.EmptyIfNull())
  {
    ...
  }
10
Andrew Hanlon

Dans votre exemple d'origine, vous utilisez un tableau vide pour fournir un énumérable vide. Bien que l'utilisation de Enumerable.Empty<T>() soit parfaitement correcte, il pourrait y avoir d'autres cas: si vous devez utiliser un tableau (ou le IList<T> interface), vous pouvez utiliser la méthode

System.Array.Empty<T>()

ce qui vous aide à éviter les allocations inutiles.

Notes/Références:

7
ventiseis

L'utilisation de Enumerable.Empty<T>() avec des listes présente un inconvénient. Si vous remettez Enumerable.Empty<T> dans le constructeur de liste puis un tableau de taille 4 est alloué. Mais si vous remettez un Collection vide dans le constructeur de liste, aucune allocation ne se produit. Donc, si vous utilisez cette solution dans tout votre code, l'un des IEnumerable sera probablement utilisé pour construire une liste, ce qui entraînera des allocations inutiles.

1
sjb-sjb

Microsoft a implémenté `Any () 'comme ceci ( source )

public static bool Any<TSource>(this IEnumerable<TSource> source)
{
    if (source == null) throw new ArgumentNullException("source");
    using (IEnumerator<TSource> e = source.GetEnumerator())
    {
        if (e.MoveNext()) return true;
    }
    return false;
}

Si vous souhaitez enregistrer un appel sur la pile d'appels, au lieu d'écrire une méthode d'extension qui appelle !Any(), réécrivez simplement ces trois modifications:

public static bool IsEmpty<TSource>(this IEnumerable<TSource> source) //first change (name)
{
    if (source == null) throw new ArgumentNullException("source");
    using (IEnumerator<TSource> e = source.GetEnumerator())
    {
        if (e.MoveNext()) return false; //second change
    }
    return true; //third change
}
1
user2023861