Кроме классов типа interface полиморфными могут быть классы типа class, struct и delegate, а также методы.
Описание полиморфного типа должно быть оформлено так, как это указано выше в примере интерфейса IComparable. Число параметров-типов может быть любым .
Описание полиморфного класса может содержать ограничения (constraints) на параметры-типы. Для этого используется служебное слово where (где). Например, описание вида.
public class AClass where T: struct {}.
означает, что тип параметров T ограничен типами-значениями.
Вместо служебного слова struct, как в данном примере, могут стоять следующие выражения.
class — только ссылочные типы;
BaseClass — только класс с именем BaseClass или его наследники;
InterfaceName — только интерфейс InterfaceName и классы, его реализующие;
new () — только классы, имеющие конструктор без параметров.
Ограничения могут образовывать список — перечисляться через запятую. Ограничение new () должно находиться в конце списка ограничений.
При отсутствии списка ограничений тип T считается не связанным условиями (unbounded).
Наследование полиморфных классов от обычных допустимо без ограничений.
Наследование обычного класса от полиморфного допустимо лишь, если полиморфный класс-предок явно определяет тип своего параметра-типа. Наследование полиморфного класса от другого полиморфного, но с бульшим числом параметров-типов, допустимо лишь, если полиморфный класс-предок явно определяет типы своих параметров, когда их несколько и они не входят в число параметров наследника. Источник этих ограничений в том, что в C# конструктор класса-наследника автоматически вызывает конструктор класса-предка. Если параметр-тип у наследника полиморфного класса не определен, вызов конструктора класса-предка не имеет смысла.
Создать экземпляр полиморфного класса можно только при явном указании параметра-типа.
Например, наберите в пространстве имен StringTestProject текущего проекта (вне или внутри тела класса StringTest, но вне тела метода Main) описание двух пустых классов.
class AClass where T: struct {}.
struct AStruct {}.
Далее, в методе Main класса StringTest того же файла наберите описания двух экземпляров полиморфного класса AClass в форме.
AClass AClassIntInstance = new AClass ();
AClass AClassAStrctInstance = new AClass ();
Компиляция должна пройти без ошибок.
Но, если в том же методе Main добавить описание вида.
AClass AClassStringInstance = new AClass ();
компилятор обозначит ошибку — ограничение struct, накладываемое на тип T полиморфного класса AClass, не позволяет использовать в качестве параметра T тип string, относящийся к ссылочным типам. Уберите не верно составленную строку кода.