2012-07-04 9 views
12

Estoy tratando de codificar un método de extensión LINQ MinByC# prueba si la variable asignada

public static class Extensions 
{ 
    public static T MinBy<T>(this IEnumerable<T> source, Func<T,int> selector) 
    { 
     T min; 
     int? minKey = null; 
     foreach (var x in source) 
     { 
      var key = selector(x); 
      if (minKey == null || key < minKey) 
      { 
       minKey = key; 
       min = x; 
      } 
     } 
     if (minKey == null) 
     { 
      throw new ArgumentException("source should not be empty"); 
     } 
     return min; 
    } 
} 

Creo que mi lógica es correcta y legible. Pero me da un error de generación

El uso de variable local no asignada 'min'

Qué puedo hacer acerca de esto? ¿Puedo probar si la variable está asignada?


Aclaración: Una función MinBy puede responder a la siguiente pregunta. ¿Cuál de los números [-5, -2, 3] tiene el cuadrado más pequeño?

> new List<int>{-5,-2,3}.MinBy(x => x*x) 
-2 

función Min de .NET responde a una pregunta diferente (que es la más pequeña de las plazas)

> new List<int>{-5,-2,3}.Min(x => x*x) 
4 
+0

IQueryable <> sería aún mejor que IEnumerable <> en mi humilde opinión de este. – Alex

+0

¿Qué es IQueryable? –

+0

Compruébelo en MSDN, es un tipo de colección que permite el encadenamiento de consultas, muy poderoso. – Alex

Respuesta

23

Se necesita un valor predeterminado para min así:

T min = default(T);

You can read more about default() on MSDN:

Dada una variable t de un tipo parametrizado T, la instrucción t = nulo solo es válida si T es un tipo de referencia yt = 0 solo funcionará para tipos de valores numéricos pero no para estructuras. La solución es utilizar la palabra clave por defecto, que devolverá nulo para los tipos de referencia y cero de los tipos de valores numéricos. Para estructuras, se volverá cada miembro de la estructura inicializado a cero o nula dependiendo de si son tipos de valor o de referencia. Para los tipos de valores que aceptan valores de nulos, el valor predeterminado es System.Nullable, que se inicializa como cualquier estructura.

+0

Gracias. ¿Esto rompe mi lógica? Después de pensar un poco, no. –

1

Eso es porque min se asigna dentro de la condición. El compilador no puede determinar si obtendrá un valor o no, debe inicializar min con el valor default.

4

Añadir un valor predeterminado para min:

T min = default(T); 

La razón de que se queja es que el compilador no puede verificar que min se habrá asignado un valor antes de que se utiliza en la línea return min;. No se puede hacer referencia a una variable local no asignada, por lo que el compilador genera un error.

-1

FYI esto es lo que terminó con

public static T MinBy<T>(this IEnumerable<T> source, Func<T,int> selector) 
    { 
     T min = default(T); 
     bool started = false; 
     int minKey = default(int); 
     foreach (var x in source) 
     { 
      var key = selector(x); 
      if (!started || key < minKey) 
      { 
       minKey = key; 
       min = x; 
       started = true; 
      } 
     } 
     if (!started) 
     { 
      throw new ArgumentException("source should not be empty","source"); 
     } 
     return min; 
    } 
-1

Sin, no se puede probar si se asigna una variable, siempre obtendrá un error de compilación.

Cuestiones relacionadas