Istnieją pewne klasy w Framework, które skutecznie przekazują specjalne cechy wszystkim typom z nich pochodnym, ale same nie posiadają tych cech . Sam CLR nie nakłada zakazu używania tych klas jako ograniczeń, ale typy ogólne ograniczone do nich nie uzyskałyby niedziedziczonych cech, tak jak typy konkretne. Twórcy C # zdecydowali, że ponieważ takie zachowanie może dezorientować niektórych ludzi, a nie dostrzegli w nim żadnej użyteczności, powinni raczej zakazać takich ograniczeń, niż pozwolić im zachowywać się tak, jak robią w CLR.
Gdyby na przykład wolno było pisać void CopyArray<T>(T dest, T source, int start, int count)
:; można by przekazać dest
i source
do metod, które oczekują argumentu typu System.Array
; ponadto, można by uzyskać walidację w czasie kompilacji, że dest
i source
były zgodne typy tablic, ale nie można uzyskać dostępu do elementów tablicy za pomocą []
operatora.
Niemożność użycia Array
jako ograniczenia jest przeważnie dość łatwa do obejścia, ponieważ void CopyArray<T>(T[] dest, T[] source, int start, int count)
będzie działać w prawie wszystkich sytuacjach, w których zadziała pierwsza metoda. Ma jednak pewną wadę: pierwsza metoda działałaby w scenariuszu, w którym jeden lub oba argumenty były typu, System.Array
podczas odrzucania przypadków, w których argumenty są niezgodnymi typami tablicowymi; dodanie przeciążenia, w którym oba argumenty byłyby typu System.Array
, spowodowałoby, że kod zaakceptowałby dodatkowe przypadki, które powinien zaakceptować, ale także błędnie zaakceptowałoby przypadki, których nie powinien.
Uważam, że decyzja o zdelegalizowaniu większości specjalnych ograniczeń jest irytująca. Jedynym, który miałby zerowe znaczenie semantyczne, byłoby System.Object
[ponieważ gdyby było to legalne jako ograniczenie, wszystko by je spełniało]. System.ValueType
prawdopodobnie nie byłby zbyt przydatny, ponieważ referencje typu ValueType
tak naprawdę nie mają wiele wspólnego z typami wartości, ale prawdopodobnie mogą mieć jakąś wartość w przypadkach obejmujących odbicie. Oba System.Enum
i System.Delegate
miałyby pewne rzeczywiste zastosowania, ale ponieważ twórcy C # nie pomyśleli o nich, są wyjęci spod prawa bez dobrego powodu.