2009-12-06 12 views
43
  • Perché non è possibile utilizzare un vincolo di where T : System.ValueType?
  • Perché Microsoft impedisce a questo tipo di di essere un vincolo?

Esempio:Perché non posso utilizzare System.ValueType come un vincolo generico?

Perché non posso effettuare le seguenti operazioni?

// Defined in a .Net class 
public void bar<T>(T a) where T : ValueType {...} 

// Defined in my class 
public void foo<T>(T a) where T : ValueType 
{ bar<T>(a); } 

Qual è la differenza nell'uso di struct sopra ValueType?

// Defined in my class 
public void foo<T>(T a) where T : struct 
{ bar<T>(a); } 

risposta

60

Ci sono due differenze tra l'utilizzo

where T : struct 

e

where T : ValueType 
  • quest'ultimo permetterebbe T di essere ValueType stessa, che è un tipo di riferimento.
  • quest'ultimo consentirebbe anche T di essere un tipo di valore nullable

La prima di queste differenze è quasi mai quello che si vuole. Il secondo potrebbe essere occasionalmente essere utile; Nullable<T> è leggermente strano in quanto non soddisfa né il vincolo where T : structwhere T : class.

Più utile sarebbe il vincolo

where T : struct, System.Enum 

che è vietato dalla C# per nessuna buona ragione che posso dire. Vedi my blog post e il Unconstrained Melody project per ulteriori informazioni.

+6

Devo dire che mi sono sempre meravigliato di non poterli limitare come 'where T: struct, System.Enum'. Sarebbe * così utile * a volte! –

+0

Si _can_ effettivamente 'dove T: Enum' e' dove T: ValueType' in F # (usando la sua sintassi 'quando 'T:> Enum') e in effetti, funziona come Jon si aspetta che funzioni. Per il vincolo enum-type, funziona con enumerici generici come 'enum ' e 'Sistema.Enum', e vieta correttamente anche i tipi di valore come 'byte' o' int'. Per rispondere alla domanda di Jon sul "perché" è così difficile da aggiungere a C#, vedi questa discussione su Roslyn: https://github.com/dotnet/roslyn/issues/262 – Abel

12

ValueType non è la classe base di tipi di valore, è semplicemente un contenitore per il valore quando viene confezionato. Poiché si tratta di una classe contenitore e non di una gerarchia per i tipi effettivi che si desidera utilizzare, non è utile come un vincolo generico.

+0

Non abbastanza e non completamente. In IL è possibile vedere chiaramente la dichiarazione di qualsiasi tipo di valore che ha "estende System.ValueType", che la rende effettivamente la classe base. Penso che il suo ruolo principale sia quello di distinguere tra una classe e un tipo di valore, ma non ne sono sicuro. – Abel

6

L'utilizzo di struct come un vincolo generico è funzionalmente equivalente a un vincolo "ValueType". In .NET, a struct is a value type.

+0

Una struct è un 'ValueType', sì, ma non ogni tipo di valore è una struct, per esempio,' ValueType' stesso non è una struct, né sono valori di valori nullable. – Abel

Problemi correlati