2012-03-27 17 views
7

Dada la siguiente firma de método, ¿por qué cuando un parámetro recibe un nombre explícito, el compilador no puede inferir automáticamente el tipo? Visual Studio 2010 SP1 puede inferir el tipo y no muestra advertencias o errores.No se puede inferir el tipo genérico con los parámetros opcionales

IEnumerable<T> ExecuteCommand<T>(
    string commandText, 
    string connectionName = null, 
    Func<IDataRecord, T> converter = null) { ... } 

static SomeClass Create(IDataRecord record) { return new SomeClass(); } 

void CannotInferType() { 
    var a = ExecuteCommand(
     "SELECT blah", 
     "connection", 
     converter: Test.Create); 
} 

void CanInferType() { 
    var a = ExecuteCommand(
     "SELECT blah", 
     "connection", 
     Test.Create); 
} 

Llamarlo como se describe en CannotInferType y al intentar compilar el compilador emite error CS0411: The type arguments for method 'Test.ExecuteCommand<T>(string, string, System.Func<System.Data.IDataRecord,T>)' cannot be inferred from the usage. Try specifying the type arguments explicitly. Mientras que calificó como se describe en CanInferType funciona como se espera.

Como se indicó anteriormente, Visual Studio no informa de ningún problema, y ​​intellisense para la variable a muestra IEnumerable<SomeClass> como se esperaba, pero por alguna razón no compila.

+0

Hubiera sido útil si hubiera dado un ejemplo corto pero * completo * ... –

Respuesta

7

Era un error en el compilador C# 4. Se ha corregido en el compilador C# 5.

Sospecho que no es el parámetro opcional el que está causando el problema aquí: es el argumento con nombre. Intenta eliminar los valores predeterminados para tus parámetros y sospecho que seguirás teniendo el mismo problema. (Vale la pena diferenciar entre parámetros opcionales y argumentos con nombre: son dos funciones separadas. A menudo se usan juntos, pero ciertamente no tienen que serlo)

Esa es la conclusión a la que recurrí cuando envié este error informe a Eric y Mads:

using System; 

class Test 
{ 
    static void Foo<T>(Func<T> func) {} 

    static void Main() 
    { 
     // Works fine 
     Foo(() => "hello"); 

     // Type inference fails 
     Foo(func:() => "hello"); 
    } 
} 

Felizmente esto ahora trabaja en la beta compilador de C# 5.

Cuestiones relacionadas