Ответ
При создании generic-типов в C# существуют следующие ключевые ограничения и правила:
1. Ограничения на наследование:
- Нельзя наследовать generic-класс от параметра типа:
class MyClass<T> : T {}— приведёт к ошибке компиляции.
2. Ограничение new():
- Если указано
where T : new(), типTобязан иметь публичный конструктор без параметров.
3. Ограничения на категорию типа:
where T : struct // T должен быть типом значения (кроме Nullable<T>)
where T : class // T должен быть ссылочным типом
where T : notnull // T должен быть не-nullable типом (C# 8.0+)
4. Ограничения на интерфейсы и базовые классы:
- Можно требовать реализацию нескольких интерфейсов и/или одного конкретного класса.
where T : BaseEntity, IComparable<T>, new()
5. Запрещённые ограничения:
- Нельзя напрямую указывать
enum,delegateили тип массива как ограничение. Дляenumможно использоватьwhere T : struct, Enum(C# 7.3+).
6. Ковариантность и контравариантность (in/out):
- Можно объявить только в интерфейсах и делегатах, и только для ссылочных типов.
Практический пример с ограничениями:
public class DataRepository<T> where T : class, IEntity, new()
{
public T CreateEntity()
{
return new T(); // Корректно, так как есть ограничение new()
}
public void Save(T entity) where T : IEntity
{
// entity гарантированно реализует IEntity
entity.Id = GenerateId();
}
}
Использование ограничений повышает безопасность типов и позволяет компилятору разрешать вызовы определённых методов или конструкторов.