Можно ли предположить то, что причина не состоит в том, чтобы позволить запечатанным классам для ограничений типа в дженериках? У меня только есть одно объяснение, должен дать возможность использовать явные ограничения.
Если класс опечатан, то он не может быть наследуемым. Если он не может быть унаследован, он будет единственным типом, действительным для аргумента общего типа [предполагая, что если разрешено быть аргументом типа]. Если это единственный общий аргумент типа, то нет смысла делать его общим! Вы можете просто кодировать против типа в не генерическом классе.
Вот код для этого.
public class A
{
public A() { }
}
public sealed class B : A
{
public B() { }
}
public class C<T>
where T : B
{
public C() { }
}
Это приведет к ошибке компилятора: 'B' не является действительным ограничением. Использованный тип как ограничение должно быть интерфейсом, незапечатанный класс или тип параметр.
В дополнение к этому, Вы также не можете иметь статический класс как generic type-constraint. Причина проста. Статические классы в компилированной IL помечены как абстрактные и опечатанные, которые не могут быть ни инстанциированы, ни наследованы.
Вот код для этого.
public class D<T>
where T : X
{
public D() { }
}
public static class X
{
}
Это приведет к ошибке компилятора:'X': статические классы нельзя использовать как Ограничения.
Обнаженное ограничение - это когда один общий тип наследуется от другого, например
where X:Y
Один общий параметр наследуется от другого общего параметра
class Foo<T>
{
Foo<S> SubsetFoo<S>() where S : T { }
}
Так что класс не может быть запечатан.
Вы также можете наследовать от дженериков обычным способом, так что вы не захотите, чтобы они были запечатаны.
Вы говорите о чем-то подобном:
class NonSealedClass
{
}
class Test<T> where T : NonSealedClass
{
}
Потому что это абсолютно законно.
Честно говоря, я не совсем понимаю смысл этого.
Как this.__curious_geek указывает в своем ответе, запечатанный класс не может наследоваться, и поэтому использование его в качестве ограничения может показаться бессмыслицей.
Но нет никакой гарантии, что запечатанный класс никогда не будет "снят" - то есть, что разработчик может изменить его реализацию, чтобы сделать его более удобным для наследования, а затем удалить модификатор sealed
из определения класса (или просто удалить ключевое слово sealed
без всякой причины).
Я знаю, что многие разработчики на самом деле поощряют такую практику: не удаление ключевого слова sealed
как такового, а скорее добавление ключевого слова sealed
и поддержка наследования только тогда, когда решение об этом принято явно (и в этот момент, да, удаление ключевого слова sealed
).
Поэтому я не уверен, почему вы не можете использовать тип запечатанного класса в качестве общего ограничения. В конце концов, вы всегда можете использовать тип класса, который случайно не имеет производных классов, даже если он не запечатан. Эти два сценария не кажутся мне такими уж разными.
Хотя, возможно, я что-то упускаю. Я уверен, что Eric Lippert мог бы дать довольно убедительное объяснение.