2011-12-15 12 views
18

Quando si definiscono i vincoli di un parametro di tipo generico, dobbiamo inserire class() nella parte anteriore e new() alla fine, ad esempio.Perché alcuni ordini sono forzati nei vincoli dei parametri generici?

Perché è questo, perché non riesco a mettere i miei vincoli in qualsiasi ordine?

Ci sono altre restrizioni sull'ordinazione oltre allo class/struct al primo posto, new() alla fine?


Esempio:

protected T Clone<T>() where T : class, ICopyable<T>, new() 
+6

Come sfondo, la specifica della lingua stabilisce che i vincoli devono essere nel vincolo di ordine * primario, vincolo secondario, vincolo di costruttore *, dove un * vincolo primario * è semplicemente * class * o * struct *, un * vincolo secondario * è una determinata interfaccia o tipo di classe, e il * constructor constraint * è semplicemente il * new() *. Per quanto riguarda il motivo per cui sono classificati come tali e richiedono quell'ordine, non ne ho idea. Forse le specifiche del linguaggio annotate farebbero luce su di esso? –

+0

Interessante, grazie. È il motivo per cui sono particolarmente interessato. –

risposta

23

Non c'è alcuna ragione particolare per cui è stato scelto questo ordine. L'ordine scelto va da più generale a più specifico, che suppongo sia una proprietà ragionevolmente bella.

Per quanto riguarda la domanda "perché richiedere un ordine?", È semplicemente più semplice per i team di implementazione e testing avere un ordine chiaro e univoco imposto dalla lingua. Potremmo permettere che i vincoli vengano in qualsiasi ordine, ma che cosa ci compri?

Più lavoro su lingue e più sono dell'opinione che ogni volta che si concede all'utente una scelta, si dà loro l'opportunità di fare una scelta sbagliata. Un principio di progettazione di base di C# è che ti diciamo quando le cose sembrano sbagliate e ti costringono a renderle ragionevoli - che non è un principio di base del design, per esempio, di JavaScript. Il suo principio di base è "confusione e prova a fare ciò che l'utente intendeva". Inserendo più restrizioni sulla sintassi corretta in C#, è possibile garantire che la semantica prevista sia espressa correttamente nel programma.

Per esempio, se io fossi la progettazione di un linguaggio C# -come oggi non c'è modo che avrei dovuto sintassi ambigue come:

class C : X , Y 

o

... where T : X, Y 

Y è chiaramente destinato ad essere un'interfaccia È X? Non possiamo dire sintatticamente se X fosse inteso come un'interfaccia o una classe. Basti dire che questa ambiguità complica molto le cose come il rilevamento dei cicli nei tipi di base e nelle interfacce e così via. Sarebbe molto più facile per tutti se fosse più verboso, come lo è in VB.

+1

+1 Grazie per il tempo dedicato a fornire alcune informazioni sul tipo di decisioni che vengono prese e sul perché. –

+2

Ho sempre trovato strano che C# esprima l'ereditarietà e l'implementazione di interfacce in modo diverso rispetto a Java (che lo fa esplicitamente), quando C# è così pesantemente influenzato da Java in molti altri aspetti. È ancora più strano visto che, come dici tu, complica il lavoro dei compilatori. – MgSam

+0

"più facile sul team di implementazione e testing" .. che mi sorprende. Anche se l'implementazione di una grammatica più piccola è probabilmente un po 'più semplice, ora hai un'intera funzione extra da implementare e testare: "Genera un errore quando l'ordine è sbagliato" –

1

Come la maggior parte delle domande relative alla sintassi, la risposta di base è perché le specifiche lo dicono. Otteniamo la seguente grammatica per i vincoli di tipo generico dalla specifica C# 5.0 (Sezione 10.1.5)

tipo-parametri-vincoli:

primary-constraint 
secondary-constraints 
constructor-constraint 
primary-constraint , secondary-constraints 
primary-constraint , constructor-constraint 
secondary-constraints , constructor-constraint 
primary-constraint , secondary-constraints , constructor-constraint 

primario vincolo:

class-type 
class 
struct 

secondarie-vincoli:

interface-type 
type-parameter 
secondary-constraints , interface-type 
secondary-constraints , type-parameter 

costruttore-vincolo:

new ( ) 

Eric Lippert ha fatto un ottimo lavoro di spiegare il motivo per cui è stato progettato in questo modo, quindi non mi esporre su questo.

Problemi correlati