2009-06-02 12 views
6

tenía curiosidad para ver cómo se implementó el método SingleOrFallback en MoreLinq y descubrí algo que no había visto antes:C#: IEnumerator <T> en una instrucción using

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 qué es el IEnumerator<T> en un comunicado using? ¿Es esto algo que debería pensarse cuando se usa el foreach en un IEnumerable<T> también?

Pregunta al lado: ¿Qué hace este método exactamente? ¿Devuelve el elemento de reserva siempre que la secuencia fuente no contenga exactamente un elemento?

Respuesta

11

IEnumerator<T> extiende IDisposable, por lo que debería lo tiene en una declaración de uso. foreach hace esto automáticamente. (El no genérico IEnumeratorno extiende IDisposable pero el compilador C# aún genera código para llamar a Dispose condicionalmente. Este fue uno de los (pocos) cambios entre C# 1.0 y 1.2, donde 1.2 es la versión que se envía con .NET 1.1 , por alguna razón.)

Here's an article explicando por qué esto es importante en el contexto de los bloques de iteradores.

En cuanto a lo que hace el método:

  • Si la secuencia está vacía, la devolución del artículo repliegue
  • Si la secuencia tiene exactamente un elemento, devolverlo
  • Si la secuencia tiene más de una elemento, una excepción

PS: es bueno ver MoreLinq está recibiendo algo de atención :)

+1

Jeje, sí. Se agregó a nuestro proyecto debido a los métodos MaxBy y MinBy. Y al agregar algo así, siempre debe verificar si hay algo más que pueda usar;) – Svish

+0

No estoy seguro de qué es útil este método SingleOrFallback ... ¿podría explicar para qué lo usa? Comprenda qué es lo que hace ahora, pero no cuándo usaría dicho método: p – Svish

+0

Claro: suponga que tiene una búsqueda que debe devolver un solo resultado, si corresponde. Desea tener algún tipo de valor predeterminado para si no devuelve nada, pero muere si hay más de un resultado (ya que eso indica un error). Básicamente es SingleOrDefault pero con un valor predeterminado especificado como una función que no se llamará a menos que sea necesario. –

0

Algunos enumeradores se comportarán mal si no se llama Dispose; esto es tan cierto para los no genéricos como los genéricos (los no genéricos requieren ese código, ya sea de tipo pato, la llamada Dispose o de lo contrario, se convierte en IDisposable y luego se llama a IDisposable.Dispose). Es una buena costumbre asegurarse de que los objetos IEnumerator sean eliminados; Lo consideraría necesario para la corrección de cualquier rutina que acepte un tipo IEnumerable de tipo desconocido.

Cuestiones relacionadas