C #: IEnumerator em uma instrução using
-
06-09-2019 - |
Pergunta
Eu estava curioso para ver como o método SingleOrFallback
foi implementado em MoreLINQ e descobriu algo Eu não tinha visto antes:
public static T SingleOrFallback<T>(this IEnumerable<T> source, Func<T> fallback)
{
source.ThrowIfNull("source");
fallback.ThrowIfNull("fallback");
using (IEnumerator<T> iterator = source.GetEnumerator())
{
if (!iterator.MoveNext())
{
return fallback();
}
T first = iterator.Current;
if (iterator.MoveNext())
{
throw new InvalidOperationException();
}
return first;
}
}
Por que o IEnumerator<T>
em um comunicado using
? Isto é algo que deve ser pensado quando se utiliza o foreach
em um IEnumerable<T>
também?
questão Side: O que este método faz exatamente? Será que devolver o item fallback sempre que a seqüência de origem não contém exatamente um produto?
Solução
IEnumerator<T>
estende IDisposable
, então você deve tê-lo em uma instrução using. foreach
faz isso automaticamente. (O IEnumerator
não-genérico não estender IDisposable
mas o compilador C # ainda gera código para Dispose
chamada condicionalmente. Este foi um dos (poucos) variar entre C # 1.0 e 1.2, onde 1.2 é a versão transporte com .NET 1.1, por algum motivo).
Aqui está um artigo explicar por que isso é importante no contexto do iterador blocos.
Quanto ao que o método faz:
- Se a sequência estiver vazia, retornar o item fallback
- Se a sequência tem exatamente um item, devolvê-lo
- Se a sequência tem mais de um item, lançar uma exceção
PS: É bom ver MoreLINQ está recebendo alguma atenção:)
Outras dicas
Alguns recenseadores irão se comportar mal se Descarte não é chamado; isso é tão verdadeiro para os não-genéricos como os genéricos (os não-genéricos requerem que o código seja pato-digite a chamada Descarte ou então elenco para IDisposable e depois chamar IDisposable.Dispose). É bom como uma questão de hábito para garantir que os objetos IEnumerator obter eliminados; Eu considero que é necessário para correção de qualquer rotina que aceita um IEnumerable de tipo desconhecido.