it-swarm-pt.tech

Existe um singleton "Lista Vazia" em C #?

Em C # eu uso LINQ e IEnumerable um pouco. E tudo está indo bem (ou pelo menos principalmente).

No entanto, em muitos casos, acho que preciso de um IEnumerable<X> Vazio como padrão. Ou seja, eu gostaria

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

para trabalhar sem precisar de uma verificação nula. Agora é isso que eu faço atualmente, dependendo do contexto maior:

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

Agora, enquanto o acima é perfeitamente adequado para mim - isto é, se houver alguma "sobrecarga extra" na criação do objeto de matriz I simplesmente não me importo - eu queria saber:

Existe o singleton "vazio imutável IEnumerable/IList" em C # /. NET? (E, mesmo se não houver, existe uma maneira "melhor" de manipular o caso descrito acima?)

Java possui Collections.EMPTY_LIST singleton imutável - "bem digitado" via Collections.emptyList<T>() - que serve a esse propósito, embora eu não seja Certifique-se de que um conceito semelhante possa funcionar em C # porque os genéricos são tratados de maneira diferente.

Obrigado.

64
user166390

Você está procurando Enumerable.Empty<int>();

Em outras notícias, a lista vazia Java Java é uma porcaria porque a interface List expõe métodos para adicionar elementos à lista que geram exceções.

82
Stilgar

Enumerable.Empty<T>() é exatamente isso.

50
Jon

Eu acho que você está procurando Enumerable.Empty<T>() .

A lista vazia singleton não faz muito sentido, porque as listas geralmente são mutáveis.

18
svick

Eu acho que adicionar um método de extensão é uma alternativa limpa, graças à sua capacidade de lidar com nulos - algo como:

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

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

No seu exemplo original, você usa uma matriz vazia para fornecer um enumerável vazio. Enquanto usar Enumerable.Empty<T>() estiver perfeitamente correto, poderá haver outros casos: se você precisar usar uma matriz (ou o IList<T> interface), você pode usar o método

System.Array.Empty<T>()

o que ajuda a evitar alocações desnecessárias.

Notas/Referências:

7
ventiseis

Usar Enumerable.Empty<T>() com listas tem uma desvantagem. Se você entregar Enumerable.Empty<T> no construtor da lista, uma matriz de tamanho 4 é alocada. Mas se você entregar um Collection vazio no construtor da lista, nenhuma alocação ocorrerá. Portanto, se você usar esta solução em todo o código, provavelmente um dos IEnumerables será usado para construir uma lista, resultando em alocações desnecessárias.

1
sjb-sjb

A Microsoft implementou `Any () 'assim ( 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;
}

Se você quiser salvar uma chamada na pilha de chamadas, em vez de escrever um método de extensão que chame !Any(), basta reescrever faça essas três alterações:

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