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