2011-03-09 20 views
10

Tener estas definiciones básicassimple expresión LINQ no se compilará

bool MyFunc(string input) 
{ 
    return false; 
} 
var strings = new[] {"aaa", "123"}; 

Me pregunto por qué esto no se compilará:

var b = strings.Select(MyFunc); 

pero esto:

var c = strings.Select(elem => MyFunc(elem)); 

El mensaje de error es "Los argumentos de tipo para el método 'System.Linq.Enumerable.Select (System.Collections.Generic.IEnumerab le, System.Func) 'no se puede deducir del uso ".

La punta de error ReSharper dice que está confundido entre

Select(this IEnumerable<string>, Func<string, TResult>) 

y

Select(this IEnumerable<string>, Func<string, int, TResult>) 

... pero la firma de MyFunc está claro - sólo se necesita un parámetro (cadena).

¿Alguien puede arrojar algo de luz aquí?

Respuesta

14

La inferencia de tipo genérico cambió ligeramente, en términos de implementación, entre el compilador C# 3 y C# 4. He aquí una breve pero completo programa de ejemplo:

using System; 
using System.Linq; 

class Test 
{ 
    static void Main() 
    { 
     string[] strings = { "a", "b" }; 
     var results = strings.Select(MyFunc); 
    } 

    static bool MyFunc(string input) 
    { 
     return true; 
    } 
} 

que compila con el compilador de C# en .NET 4, pero no el de .NET 3.5.

Yo creo es razonable llamar a esto una corrección de errores, ya que no hago piensan que era un cambio de especificaciones.

Si usted tiene que utilizar el compilador de .NET 3.5, se puede añadir un molde para aclarar:

var results = strings.Select((Func<string,bool>) MyFunc); 

o

var results = strings.Select(new Func<string,bool>(MyFunc)); 

o usted podría hacer que el argumento de tipo explícito:

var results = strings.Select<string, bool>(MyFunc); 
+0

Por lo tanto, * no era * no razonable de que yo creo que el compilador resolvería las cosas ... –

+0

@Cristi: No ...aunque tratar de discernir a partir de las especificaciones exactamente cómo debería funcionar es complicado. Pienso en la parte de inferencia de tipo de la especificación que tiene "Here be dragons" escrito por todas partes. –

+0

Decidimos cambiar el comportamiento cuando resultó demasiado tarde para obtener el cambio a C# 3, por lo que lo pusimos en C# 4 en su lugar. –

6

Jon es, por supuesto, correcto como de costumbre. Alguna información adicional:

Aquí está el artículo del blog de 2007, donde describo el problema que está teniendo:

http://blogs.msdn.com/b/ericlippert/archive/2007/11/05/c-3-0-return-type-inference-does-not-work-on-member-groups.aspx

Basándose en la información sobre ese artículo decidimos solucionar este problema, pero no pudo conseguir la solución en C# 3 por razones de programación.

Unos meses después de que anuncié que el arreglo entraría en C# 4, no en el paquete de servicio C# 3:

http://blogs.msdn.com/b/ericlippert/archive/2008/05/28/method-type-inference-changes-part-zero.aspx

Cuestiones relacionadas