C# в 2025 году: новые возможности на практике

Онлайн-тренажер Python для начинающих

Изучайте Python легко и без перегрузки теорией. Решайте практические задачи с автоматической проверкой, получайте подсказки на русском языке и пишите код прямо в браузере — без необходимости что-либо устанавливать.

Начать курс

C# в 2025 году: что нового на практике?

Мир .NET не стоит на месте. В 2025 году язык C# продолжает активно развиваться, предлагая разработчикам инструменты для написания более лаконичного, безопасного и производительного кода. Каждое обновление платформы делает повседневную разработку удобнее, а новые языковые конструкции позволяют избавиться от шаблонного кода.

В этой статье мы разберём три ключевых нововведения C# в 2025 году, которые вы можете начать использовать прямо сейчас. Все примеры кода взяты из реальной практики и адаптированы для образовательного портала pythonlib.ru.

1. Первичные конструкторы (Primary Constructors)

Одно из самых ожидаемых нововведений — это первичные конструкторы для классов и структур. Ранее такая возможность была доступна только для записей (record). Теперь вы можете объявить параметры конструктора прямо в заголовке класса, что значительно сокращает объём кода.

Рассмотрим классический пример создания модели пользователя:

Было (C# 12 и ранее):

public class User
{
    public string Name { get; }
    public int Age { get; }

    public User(string name, int age)
    {
        Name = name;
        Age = age;
    }
}

Стало (C# 2025):

public class User(string name, int age)
{
    public string Name { get; } = name;
    public int Age { get; } = age;
    
    public string Greeting => $"Привет, {Name}! Тебе {Age} лет.";
}

Как видите, код стал чище. Параметры name и age теперь доступны во всём теле класса. Это особенно удобно при работе с Dependency Injection (DI) в ASP.NET Core:

public class WeatherService(HttpClient httpClient, ILogger<WeatherService> logger)
{
    public async Task<string> GetWeatherAsync(string city)
    {
        logger.LogInformation("Запрос погоды для города {City}", city);
        var response = await httpClient.GetStringAsync($"https://api.weather.com/{city}");
        return response;
    }
}

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

2. Коллекции нового образца (Collection Expressions)

В 2025 году C# получил мощное обновление для работы с коллекциями. Теперь вы можете инициализировать списки, массивы и даже Span<T> единым синтаксисом — collection expressions.

Новый синтаксис использует квадратные скобки [] вместо фигурных {} или new List<T>():

Пример инициализации различных коллекций:

// Массив
int[] numbers = [1, 2, 3, 4, 5];

// Список
List<string> names = ["Анна", "Борис", "Виктор"];

// Span (работает без аллокаций)
Span<char> letters = ['A', 'B', 'C'];

Главная фишка — оператор распаковки (spread) ... Он позволяет объединять коллекции без вызова .Concat() или .AddRange():

int[] first = [1, 2, 3];
int[] second = [4, 5, 6];

// Объединение массивов
int[] combined = [..first, ..second]; // [1, 2, 3, 4, 5, 6]

// Добавление элементов в начало и конец
int[] extended = [0, ..combined, 7]; // [0, 1, 2, 3, 4, 5, 6, 7]

Этот синтаксис работает не только с массивами, но и с List<T>, HashSet<T> и даже с пользовательскими коллекциями, реализующими ICollection<T>. Для разработчиков, привыкших к Python, такой подход покажется очень знакомым и интуитивным.

3. Улучшенная интерполяция строк и обработка исключений

Интерполяция строк в C# 2025 получила несколько важных улучшений, которые делают её ещё более гибкой.

3.1. Интерполяция в операторах nameof

Теперь вы можете использовать nameof с интерполированными строками. Это упрощает логирование и работу с отражением:

string propertyName = "Age";
// Раньше: nameof(User.Age) — только константа
// Теперь можно динамически:
string name = nameof($"{propertyName}"); // "Age"

3.2. Улучшенная обработка исключений

В C# 2025 появилась возможность использовать throw в выражениях с ?? (null-coalescing) и тернарных операторах:

public string GetConfig(string key)
{
    return configDictionary.GetValueOrDefault(key) 
           ?? throw new KeyNotFoundException($"Ключ '{key}' не найден.");
}

Это позволяет писать более плоский код без лишних if-блоков.

3.3. Пользовательские обработчики исключений

Новое ключевое слово catch when получило расширенную поддержку для фильтрации исключений по произвольным условиям:

try
{
    await ProcessDataAsync();
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.NotFound)
{
    LogWarning("Ресурс не найден");
}
catch (HttpRequestException ex) when (ex.StatusCode == HttpStatusCode.InternalServerError)
{
    LogError("Ошибка сервера");
    throw; // перебрасываем, если не можем обработать
}

Это делает обработку ошибок более точечной и читаемой.

Практический пример: приложение для заметок

Давайте соберём все три нововведения в одном небольшом приложении — консольном менеджере заметок:

// Используем первичный конструктор
public class Note(string title, string content)
{
    public string Title { get; } = title;
    public string Content { get; } = content;
    public DateTime CreatedAt { get; } = DateTime.UtcNow;
}

public class NoteManager
{
    private List<Note> _notes = [];

    public void AddNote(string title, string content)
    {
        _notes.Add(new Note(title, content));
    }

    public void ShowNotes()
    {
        // Используем collection expressions и интерполяцию
        var summaries = [.._notes.Select(n => $"📌 {n.Title} — {n                

Блоги

Рекомендаций по книгам