Il existe certaines classes dans le Framework qui transmettent effectivement des caractéristiques spéciales à tous les types qui en dérivent mais ne possèdent pas ces caractéristiques elles-mêmes . Le CLR lui-même n'impose aucune interdiction d'utiliser ces classes comme contraintes, mais les types génériques qui y sont contraints n'acquériraient pas les caractéristiques non héritées comme le feraient des types concrets. Les créateurs de C # ont décidé que, parce qu'un tel comportement pouvait semer la confusion chez certaines personnes et qu'ils ne voyaient aucune utilité, ils devraient interdire de telles contraintes plutôt que de leur permettre de se comporter comme ils le font dans le CLR.
Si, par exemple, on était autorisé à écrire void CopyArray<T>(T dest, T source, int start, int count)
:; on pourrait passer dest
et source
à des méthodes qui attendent un argument de type System.Array
; de plus, on obtiendrait la validation à la compilation qui dest
et source
étaient les types de tableaux compatibles, mais on ne pourrait pas accéder aux éléments du tableau en utilisant l' []
opérateur.
L'incapacité à utiliser Array
comme contrainte est généralement assez facile à contourner, car void CopyArray<T>(T[] dest, T[] source, int start, int count)
fonctionnera dans presque toutes les situations où l'ancienne méthode fonctionnerait. Elle a cependant une faiblesse: la première méthode fonctionnerait dans le scénario où l'un des arguments ou les deux étaient de type System.Array
tout en rejetant les cas où les arguments sont des types de tableaux incompatibles; l'ajout d'une surcharge où les deux arguments étaient de type System.Array
ferait en sorte que le code accepte les cas supplémentaires qu'il devrait accepter, mais aussi le ferait accepter par erreur les cas qu'il ne devrait pas.
Je trouve la décision d'interdire la plupart des contraintes spéciales ennuyeuse. Le seul qui aurait une signification sémantique nulle serait System.Object
[puisque si c'était légal comme contrainte, tout le satisferait]. System.ValueType
ne serait probablement pas très utile, car les références de type ValueType
n'ont pas vraiment grand chose en commun avec les types valeur, mais cela pourrait vraisemblablement avoir une certaine valeur dans les cas impliquant Reflection. Les deux System.Enum
et System.Delegate
aurait des utilisations réelles, mais étant donné que les créateurs de C # ne pensaient pas d'eux , ils sont mis hors la loi sans raison.