2013-02-15 5 views
9
public enum EnumTest 
{ 
    EnumEntry 
} 

public class TestClass 
{ 
    public string FunctionMember(string s, EnumTest t = EnumTest.EnumEntry) 
    { 
     return "Normal"; 
    } 

    public string FunctionMember<T>(T t) 
    { 
     return "Generic"; 
    } 
} 

class Program 
{ 
    static void Main(string[] args) 
    { 
     TestClass t = new TestClass(); 

     Console.WriteLine(t.FunctionMember("a")); 
    } 
} 

Stampa "Generico". La rimozione di , EnumTest t = EnumTest.EnumEntry lo fa stampare "Normale".Perché un membro di una funzione generica viene scelto su uno non generico?

Eppure la norma sembra essere abbastanza chiaro, da membro 14.4.2.2 migliore funzione il primo discriminatore da applicare è:

  • Se uno di MP e MQ non è generica, ma la l'altro è generico, quindi il non generico è migliore.

Mi manca qualcosa o bug del compilatore?

+0

Stai guardando le specifiche C# 4.0? Sospetto che tu stia guardando una specifica più vecchia, che non menziona i parametri opzionali, poiché quelli sono stati introdotti solo in C# 4.0. – CodesInChaos

+0

Credo che tu abbia diverse firme sui tuoi metodi. Hai provato, ad esempio, a passare un int o qualcosa? –

+0

@Codes: non lo ero ma la specifica 4.0 dice la stessa cosa, tranne che è al 7.5.3.2. –

risposta

8

Ti manca qualcosa. E questo è il seguente:

Si chiama il metodo con un parametro. C'è solo un metodo che ha un parametro, quello generico. Quindi è quello che è stato scelto.

Solo se non ha trovato un metodo di abbinamento, avrebbe esaminato altri metodi con parametri opzionali.

Riferimenti:

  1. C# 4.0 Specification, ultimo paragrafo 21.4:

    Come regola tie breaker, un membro di funzione per la quale tutti gli argomenti in cui esplicitamente indicata è meglio di uno per il quale i valori predefiniti sono stati forniti al posto di argomenti espliciti.

  2. MSDN, voce "risoluzione Overload", l'ultimo punto:

    Se due candidati sono giudicati di essere altrettanto buono, la preferenza va a un candidato che non ha parametri opzionali per il quale gli argomenti erano omesso nella chiamata. Questa è una conseguenza di una preferenza generale nella risoluzione del sovraccarico per i candidati che hanno meno parametri.

  3. The C# Language Specification, il capitolo "7.5.3.2 membro funzionare meglio":

    liste dei parametri per ciascuno dei candidati membri di funzione sono costruite nel modo seguente:

    • La forma espansa viene utilizzato se il membro della funzione era applicabile solo nella forma espansa.
    • parametri facoltativi senza corrispondenti argomenti vengono rimossi dalla lista dei parametri

    continua così:

    Data una lista di argomenti A con un insieme di espressioni argomenti {E , E , ..., E N} e due organi funzionali applicabili MP e MQ con tipi di parametri {P , P , ..., P N} e {Q , Q ,. .., Q N} [...]

    a questo punto il metodo con il parametro opzionale è già fuori dal gioco. N è 1, ma questo metodo ha due parametri.

+0

Puoi citare le specifiche per supportarlo? cioè che dover sostituire i valori di default per i parametri opzionali è "peggiore" di dover usare un metodo generico? – CodesInChaos

+0

@CodesInChaos: consultare l'aggiornamento. –

+0

oO Perché hanno inserito le funzionalità 4.0 in una bozza di documento separata? Il normale C# 4.0 specifica non contiene quei capitoli. – CodesInChaos

3

Il docs dicono:

Se due candidati sono giudicati di essere altrettanto buono, la preferenza va a un candidato che non ha parametri opzionali per i quali argomenti sono stati omessi nella chiamata. Questa è una conseguenza di una preferenza generale nella risoluzione del sovraccarico per i candidati che hanno meno parametri.

In altre parole, verrà preferito il metodo senza argomenti facoltativi.

1

Con i valori predefiniti per i parametri del metodo, la risoluzione di sovraccarico è stata estesa.

Concettualmente verrà eseguita la risoluzione del sovraccarico del metodo da pre v4. Se questo trova una corrispondenza che verrà utilizzata. (Concettualmente perché questa non è una descrizione di come funziona, ma come si può pensare di esso)

Nel tuo caso si trova un solo risultato essere il metodo generico

Se non trova una corrispondenza sembrerà per metodi che hanno una corrispondenza parziale e dove la corrispondenza può essere completata con valori predefiniti. Nel tuo caso il tuo metodo generice non sarebbe stato trovato in questa esecuzione, ma la risoluzione non arriva mai così a causa di aver già trovato una corrispondenza.

Quando si rimuove il secondo parametro si finisce in una situazione in cui vi è una corrispondenza generica e non generica. E la regola che tu hai scelto è quella di scegliere il non generico.

Tutto sommato una buona regola empirica è che verrà scelto il metodo più specifico disponibile.

Un metodo non generico che corrisponde è più specifico di un generico perché il tipo non può variare. Un metodo con parametri predefiniti è meno specifico di uno in cui il conteggio degli argomenti corrisponde al conteggio dei parametri (i numeri sono una corrispondenza esatta) se sono disponibili due metodi, ma uno accetta un argomento di IFoo e l'altro accetta un Foo (implemeting IFoo) allora quest'ultimo sarà scelto quando passerà un oggetto Foo come argomento perché è una corrispondenza esatta. più specifico

Problemi correlati