Ci sono alcune classi nel Framework che trasmettono effettivamente caratteristiche speciali a tutti i tipi da esse derivati ma non possiedono tali caratteristiche stesse . Lo stesso CLR non impone alcun divieto contro l'utilizzo di tali classi come vincoli, ma i tipi generici ad esse vincolati non acquisiscono le caratteristiche non ereditate come farebbero i tipi concreti. I creatori di C # hanno deciso che poiché tale comportamento potrebbe confondere alcune persone e non sono riusciti a vederne l'utilità, dovrebbero vietare tali vincoli piuttosto che consentire loro di comportarsi come fanno nel CLR.
Se, ad esempio, fosse consentito scrivere void CopyArray<T>(T dest, T source, int start, int count)
:; si sarebbe in grado di passare dest
e source
a metodi che prevedono un argomento di tipo System.Array
; inoltre, si otterrebbe una convalida in fase di compilazione che dest
e source
fossero i tipi di array compatibili, ma non si sarebbe in grado di accedere agli elementi dell'array utilizzando l' []
operatore.
L'incapacità di utilizzare Array
come vincolo è per lo più abbastanza facile da aggirare, poiché void CopyArray<T>(T[] dest, T[] source, int start, int count)
funzionerà in quasi tutte le situazioni in cui funzionerebbe il primo metodo. Tuttavia, ha un punto debole: il primo metodo funzionerebbe nello scenario in cui uno o entrambi gli argomenti erano di tipo System.Array
rifiutando i casi in cui gli argomenti sono tipi di array incompatibili; l'aggiunta di un sovraccarico in cui entrambi gli argomenti erano di tipo System.Array
farebbe sì che il codice accetti i casi aggiuntivi che dovrebbe accettare, ma lo farebbe anche accettare erroneamente casi che non dovrebbe.
Trovo fastidiosa la decisione di mettere fuori legge la maggior parte dei vincoli speciali. L'unico che avrebbe significato semantico zero sarebbe System.Object
[poiché se fosse legale come vincolo, qualsiasi cosa lo soddisferebbe]. System.ValueType
probabilmente non sarebbe molto utile, poiché i riferimenti di tipo ValueType
non hanno molto in comune con i tipi di valore, ma potrebbe plausibilmente avere qualche valore nei casi che coinvolgono la riflessione. Entrambi System.Enum
e System.Delegate
avrebbero alcuni usi reali, ma dal momento che i creatori di C # non ci hanno pensato, sono fuorilegge senza una buona ragione.