2012-03-27 9 views
7

Wenn die folgende Methodensignatur angegeben wird, warum kann ein Compiler den Typ nicht automatisch ableiten, wenn ein Parameter explizit benannt wird? Visual Studio 2010 SP1 kann den Typ ableiten und zeigt keine Warnungen oder Fehler an.Kann keinen generischen Typ mit optionalen Parametern ableiten

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); 
} 

es aufrufen, wie in CannotInferType beschrieben, und wenn es der Compiler zu kompilieren versuchen emittiert 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. Während es nennen wie in CanInferType Werken beschrieben, wie erwartet.

Wie oben erwähnt, meldet Visual Studio selbst keine Probleme, und intellisense für die Variable a zeigt IEnumerable<SomeClass> wie erwartet, aber aus irgendeinem Grund wird nicht kompiliert.

+0

Es wäre hilfreich gewesen, wenn Sie ein kurzes, aber * vollständiges * Beispiel gegeben hätten ... –

Antwort

7

Es war ein Fehler im C# 4-Compiler. Es wurde im C# 5-Compiler behoben.

Ich vermute, es ist nicht der optionale Parameter, der hier das Problem verursacht - es ist das benannte Argument. Versuchen Sie, die Standardwerte für Ihre Parameter zu entfernen, und ich vermute, dass Sie immer noch das gleiche Problem haben. (Es ist wert, zwischen optionalen Parametern und benannten Argumenten zu unterscheiden - sie sind zwei separate Funktionen. Sie werden oft zusammen verwendet, müssen aber nicht sein.)

Das ist die Schlussfolgerung, zu der ich kam, als ich diesen Fehler sendete Bericht an Eric und 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"); 
    } 
} 

Happily dies jetzt arbeitet in dem C# 5 beta-Compiler.