Подтвердить что ты не робот

Почему мы не можем использовать закрытые классы в качестве общих ограничений?

Можете ли вы догадаться, в чем причина не допускать закрытых классов ограничений типа в дженериках? У меня есть только одно объяснение - дать возможность использовать голые ограничения.

4b9b3361

Ответ 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 {  }
}

Таким образом, класс не может быть закрыт.

Вы также можете наследовать от дженериков обычным способом, чтобы вы не хотели, чтобы они были запечатаны.