Полное руководство по языку программирования С# 14 и платформе .NET 10 / Объектно-ориентированное программирование

Наследование обобщенных типов

Начальный ⏱ 3 мин чтения 👁 2 🕓 обновлено 11.08.2026

Один обобщенный класс может быть унаследован от другого обобщенного. При этом можно использовать различные варианты наследования.

Допустим, у нас есть следующий базовый класс Person:


class Person<T>
{
	public T Id { get;}
	public Person(T id)
	{
		Id = id;
	}
}

Первый вариант заключается в создание класса-наследника, который типизирован тем же типом, что и базовый:


class UniversalPerson<T> : Person<T>
{
	public UniversalPerson(T id) : base(id) { }
}

Применение класса:


Person<string> person1 = new Person<string>("34");
Person<int> person3 = new UniversalPerson<int>(45);
UniversalPerson<int> person2 = new UniversalPerson<int>(33);
Console.WriteLine(person1.Id);
Console.WriteLine(person2.Id);
Console.WriteLine(person3.Id);

Второй вариант представляет создание обычного необобщенного класса-наследника. В этом случае при наследовании у базового класса надо явным образом определить используемый тип:


class StringPerson : Person<string>
{
    public StringPerson(string id) : base(id) { }
}

Теперь в производном классе в качестве типа будет использоваться тип string. Применение класса:


StringPerson person4 = new StringPerson("438767");
Person<string> person5 = new StringPerson("43875");
// так нельзя написать
//Person<int> person6 = new StringPerson("45545");
Console.WriteLine(person4.Id);
Console.WriteLine(person5.Id);

Третий вариант представляет типизацию производного класса параметром совсем другого типа, отличного от универсального параметра в базовом классе. В этом случае для базового класса также надо указать используемый тип:


class IntPerson<T> : Person<int>
{
    public T Code { get; set; }
    public IntPerson(int id, T code) : base(id) 
    {
        Code = code;
    }
}

Здесь тип IntPerson типизирован еще одним типом, который может не совпадать с типом, который используется базовым классом. Применение класса:


IntPerson<string> person7 = new IntPerson<string>(5, "r4556");
Person<int> person8 = new IntPerson<long>(7, 4587);
Console.WriteLine(person7.Id);
Console.WriteLine(person8.Id);

И также в классах-наследниках можно сочетать использование универсального параметра из базового класса с применением своих параметров:


class MixedPerson<T, K> : Person<T>
    where K : struct
{
    public K Code { get; set; }
    public MixedPerson(T id, K code) : base(id)
    {
        Code = code;
    }
}

Здесь в дополнение к унаследованному от базового класса параметру T добавляется новый параметр K. Также если необходимо при этом задать ограничения, мы их можем указать после названия базового класса. Применение класса:


MixedPerson<string, int> person9 = new MixedPerson<string, int>("456", 356);
Person<string> person10 = new MixedPerson<string, int>("9867", 35678);
Console.WriteLine(person9.Id);
Console.WriteLine(person10.Id);

При этом стоит учитывать, что если на уровне базового класса для универсального параметра установлено ограничение, то подобное ограничение должно быть определено и в производных классах, которые также используют этот параметр:


class Person<T> where T : class
{
	public T Id { get;}
	public Person(T id) => Id = id;
}
class UniversalPerson<T> : Person<T> where T: class
{
	public UniversalPerson(T id) : base(id) { }
}

То есть если в базовом классе в качестве ограничение указано class, то есть любой класс, то в производном классе также надо указать в качестве ограничения class, либо же какой-то конкретный класс.

Проверь себя

📋 Тест по теме «Наследование обобщенных типов» Тест по теме

Практические задания

Лёгкое Ручная проверка Заполните пропуск в коде (1)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

class _____<T>
{
	public T Id { get;}
	public Person(T id)
	{
		Id = id;
	}
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (2)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

class Universal_____<T> : Person<T>
{
	public UniversalPerson(T id) : base(id) { }
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (3)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

Person<string> person1 = _____ Person<string>("34");
Person<int> person3 = new UniversalPerson<int>(45);
UniversalPerson<int> person2 = new UniversalPerson<int>(33);
Console.WriteLine(person1.Id);
Console.WriteLine(person2.Id);
Console.WriteLine(person3.Id);
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (4)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

class StringPerson : Person<string>
{
    public StringPerson(string id) : _____(id) { }
}
Войдите, чтобы отправить решение
Лёгкое Ручная проверка Заполните пропуск в коде (5)
+10 XP

В приведённом ниже фрагменте кода из этого урока пропущено одно слово. Определите его и впишите в поле ответа (без кавычек и пробелов).

StringPerson person4 = new StringPerson("_____");
Person<string> person5 = new StringPerson("43875");
// так нельзя написать
//Person<int> person6 = new StringPerson("45545");
Console.WriteLine(person4.Id);
Console.WriteLine(person5.Id);
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (1)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

class _____<T>
{
	public T Id { _____;}
	public Person(T id)
	{
		Id = id;
	}
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Восстановите код по памяти (2)
+20 XP

В этом фрагменте кода урока пропущены два ключевых элемента. Впишите оба пропущенных значения через запятую в порядке появления (например: x, 5).

class _____<T> : Person<T>
{
	public UniversalPerson(T id) : _____(id) { }
}
Войдите, чтобы отправить решение
Среднее Ручная проверка Расставьте строки кода в правильном порядке
+20 XP

Строки кода из примера этого урока перемешаны. Впишите их в правильном порядке, каждую строку — с новой строки.

}
		Id = id;
	public Person(T id)
	public T Id { get;}
	{
class Person<T>
{
	}
Войдите, чтобы отправить решение
Сложное Ручная проверка Объясните и модифицируйте пример из урока «Наследование обобщенных типов»
+30 XP

Опишите своими словами, что делает приведённый пример кода из урока «Наследование обобщенных типов», и предложите одно осмысленное изменение (например, другое входное значение или дополнительное условие). Приведите итоговый код.

class Person<T>
{
	public T Id { get;}
	public Person(T id)
	{
		Id = id;
	}
}
Войдите, чтобы отправить решение
Сложное Ручная проверка Найдите потенциальную проблему в коде урока «Наследование обобщенных типов»
+30 XP

Изучите приведённый фрагмент кода и опишите, при каких входных данных или условиях он может сработать не так, как ожидается (граничный случай, отсутствие проверки и т.п.). Предложите исправленный вариант.

class UniversalPerson<T> : Person<T>
{
	public UniversalPerson(T id) : base(id) { }
}
Войдите, чтобы отправить решение
Мини-проект Ручная проверка Мини-проект по теме «Наследование обобщенных типов»
+50 XP

Соберите небольшую программу, которая последовательно демонстрирует ключевые идеи урока. Программа должна быть рабочей и содержать минимум два самостоятельно написанных фрагмента, а не просто копию примера из урока.

Войдите, чтобы отправить решение
Домашнее задание Ручная проверка Домашнее задание по теме «Наследование обобщенных типов»
+25 XP

Напишите собственную небольшую программу, применяющую материал темы «Наследование обобщенных типов». Используйте не менее одной конструкции, показанной в примерах урока. Прикрепите код решения и краткое описание того, что он делает.

Войдите, чтобы отправить решение

Обсуждение (0)

Войдите, чтобы оставить комментарий.