Что делает ключевое слово new в 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, если это соответствует логике наследования.

Ответ 18+ 🔞

А, слушай, про это ваше ключевое слово new в C#... Ну, оно же, блядь, как швейцарский нож — на все случаи жизни, только вот применять надо с умом, а то можно и пальцы отрезать. Давай разберём, пока не поздно.

Первое и самое очевидное — создание всего на свете. Ну, типа, оператор new. Хочешь объект? new! Хочешь массив? new! Хочешь анонимный тип, чтобы на коленке слепить что-то безымянное? Тоже new, ёпта!

// Ну, список создали, обычное дело
var list = new List<string>();
// Человека слепили — Алиса, 30 лет, всё по-взрослому
var person = new Person("Alice", 30);

// Массив чисел? Без проблем, на тебе пять штук, хоть заполняй, хоть нет
int[] numbers = new int[5];
// Двумерный, матрица? Да хули там, new int[2, 3] и вперёд
var matrix = new int[2, 3];

// А это вообще магия: тип без имени, но с полями. Удобно, блядь, для временщиков
var anonymous = new { Name = "Bob", Age = 25 };

Вот это всё — прямолинейно и понятно. Выделил память, конструктор вызвал — живёт объект.

А вот второе применение — это уже поинтереснее. Это модификатор new. Он не создаёт нихуя, а прячет. Как твой сосед, когда должен денег. Берёшь член в классе-наследнике (метод, свойство, поле — неважно), даёшь ему такое же имя, как у родителя, и пишешь перед ним new. И всё — унаследованный член теперь в тени, как будто его и не было. Но это не переопределение (override), это просто сокрытие, обманка!

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

public class DerivedClass : 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". Новый метод работает.

Вот такая, блядь, матрешка получается. Смотря через какую переменную на объект смотреть, такой метод и вылезет. Путаница — овердохуища. Поэтому умные дядьки говорят: если хочешь полиморфизма и чтобы всё работало как часы — используй virtual и override. А new — это для особых случаев, когда ты точно знаешь, что делаешь, и готов к неожиданностям. Иначе потом будешь сидеть и думать: "Ну какого хуя оно вызывает не тот метод?!"

Ну и третье — ограничение в дженериках. Тут new() как страж у ворот. Говоришь: "Параметр типа T в моём классе-фабрике должен иметь публичный конструктор без параметров, иначе нахуй не нужен".

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

// Примеры на живца:
// var stringFactory = new Factory<string>(); // Ошибка компиляции! У string нет публичного конструктора по умолчанию.
var listFactory = new Factory<List<int>>(); // А вот это ок. List<int> такой конструктор имеет.
var instance = listFactory.CreateInstance(); // И на тебе — свеженький пустой список.

Короче, new — инструмент мощный, но, как и любой инструмент, требует понимания, куда и зачем ты его суёшь. А то можно так на new накрутить, что потом сам черт ногу сломит в своём же коде.