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.
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.
Enumerable.Empty<T>()
est exactement cela.
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.
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())
{
...
}
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:
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.
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
}