2010-04-30 17 views
5

Il seguente codice non riesce a compilare, producendo un errore "Il widget deve essere un tipo non astratto con un costruttore pubblico senza parametri". Penserei che il compilatore abbia tutte le informazioni di cui ha bisogno. è un insetto? Una svista? O c'è qualche scenario in cui ciò non sarebbe valido?Perché il nuovo vincolo generico() non è soddisfatto da una classe con parametri facoltativi nel costruttore?

public class Factory<T> where T : new() 
{ 
    public T Build() 
    { 
     return new T(); 
    } 
} 

public class Widget 
{ 
    public Widget(string name = "foo") 
    { 
     Name = name; 
    } 

    public string Name { get; set; } 
} 

public class Program 
{ 
    public static void Main() 
    { 
     var widget = new Widget(); // this is valid 
     var factory = new Factory<Widget>(); // compiler error 
    } 
} 
+0

Paging Eric Lippert .... Penso che questo sarà dovuto ai parametri facoltativi che sono una funzione del compilatore, ma i vincoli generici sono CLR. Quindi i parametri opzionali sono sostituiti dal compilatore e il JIT vede solo i parametri (necessari). – Richard

+0

@Richard: Questo è fondamentalmente il problema qui. I parametri opzionali hanno anche alcuni strani effetti collaterali per il controllo delle versioni, proprio per questo motivo ... –

risposta

7

Mentre questo dovrebbe funzionare logicamente, sfortunatamente no. Il CLR vede ancora il tuo costruttore come un costruttore basato su parametri.

Ricorda che, mentre C# supporta parametri opzionali, questo viene fatto a livello di compilatore, in fase di compilazione. Il tipo sottostante contiene ancora solo un costruttore che prende un singolo parametro. Per quanto riguarda il CLR è interessato, i "parametri di default" vengono convertiti in attributi, in questo modo:

public Widget(([Optional, DefaultParameterValue("foo")] string name) { // ... 

Il CLR è un runtime multi-lingua. I generici sono fatti per funzionare a livello di CLR, per tutte le lingue, quindi i vincoli devono essere veri anche in lingue senza parametri predefiniti. Non è richiesto alle lingue di comprendere l'attributo facoltativo, né l'attributo DefaultParameterValueAttribute, pertanto non può funzionare in modo uniforme per tutte le lingue, quindi non è consentito.


Edit:

In risposta al tuo commento:

Quello che non capisco è il motivo per cui il compilatore C# non può generare il codice necessario per soddisfare il CLR

In teoria, il team del compilatore C# potrebbe avere il linguaggio generare due distinti costruttori, invece di un costruttore contrassegnato con attributi. Ciò potrebbe, potenzialmente, esplodere in molti costruttori, poiché i parametri denominati creano le capacità per molte, molte possibili combinazioni di "costruttori" (o metodi per i metodi), specialmente quando sono disponibili più argomenti. Personalmente sono contento di non averlo fatto, poiché causerebbe confusione a causa di una sovrabbondanza di metodi e costruttori nei tipi generati, il che farebbe sì che l'API pubblica appaia molto diversa dal codice che l'ha generata. Prendere la seguente costruttore:

public Widget(
      int id = 0, 
      string name = "foo", 
      float width=1.0f, 
      float height=1.0f, 
      float depth=1.0f 
     ) { // ... 

Erano di generare automaticamente tutte le possibili combinazioni di qui, il compilatore avrebbe bisogno di generare costruttori per questo singolo costruttore, dato che ci sono N! possibili modi per chiamare questo ...

+0

@Joshua: Il compilatore C# genera il codice che ho incollato sopra. Funziona così: non sta costruendo un costruttore senza parametri, ma piuttosto uno facoltativo. Modificherò per aggiungere dettagli ... –

+0

Ok, grazie, questo spiega perché non funziona. Mi chiedo ancora quali sarebbero le implicazioni della generazione del costruttore senza parametri. –

+0

@Joshua: ho modificato la mia risposta per spiegare perché questa è potenzialmente una cattiva idea ... ha più senso ora? Ricorda, non è solo opzionale, puoi anche usare parametri con nome, quindi N parametri significa N! possibili combinazioni che dovrebbero essere generate ... –

Problemi correlati