Что делает ключевое слово new в C#?

«Что делает ключевое слово new в C#?» — вопрос из категории C# Core, который задают на 25% собеседований C# Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Ключевое слово new в C# имеет три основных контекста использования:

1. Создание экземпляров (Оператор new)

Используется для выделения памяти и вызова конструктора для создания нового объекта или массива.

// Создание объекта класса
var list = new List<string>();
var person = new Person("Alice", 30);

// Создание массива
int[] numbers = new int[5];
var matrix = new int[2, 3];

// Создание анонимного типа
var anonymous = new { Name = "Bob", Age = 25 };

2. Сокрытие членов (Модификатор new)

Позволяет члену производного класса (методу, свойству, полю) скрыть (shadow/hide) унаследованный член с тем же именем из базового класса. Это не является полиморфным переопределением (override).

public class BaseClass
{
    public void Display() => Console.WriteLine("BaseClass Display");
}

public class DerivedClass : BaseClass
{
    // Новый метод, скрывающий BaseClass.Display
    public new void Display() => Console.WriteLine("DerivedClass Display");
}

// Использование:
BaseClass obj1 = new DerivedClass();
obj1.Display(); // Вывод: "BaseClass Display" (вызывается метод базового класса)

DerivedClass obj2 = new DerivedClass();
obj2.Display(); // Вывод: "DerivedClass Display" (вызывается новый метод)

3. Ограничение универсального типа (Ограничение new())

В универсальных шаблонах указывает, что параметр типа T должен иметь открытый конструктор без параметров (конструктор по умолчанию).

public class Factory<T> where T : new() // T должен иметь public T()
{
    public T CreateInstance()
    {
        return new T(); // Можно безопасно создать экземпляр T
    }
}

// Использование:
var stringFactory = new Factory<string>(); // Ошибка компиляции! string не имеет конструктора по умолчанию.
var listFactory = new Factory<List<int>>(); // OK, List<int> имеет конструктор по умолчанию.
var instance = listFactory.CreateInstance(); // Создает новый пустой List<int>

Важное предупреждение: Использование new для сокрытия методов часто считается плохой практикой, так как может привести к путанице. Всегда предпочитайте полиморфное поведение через virtual/override, если это соответствует логике наследования.