Как работает pattern matching с оператором is в C#? Почему сочетание is с when и свойствами предпочтительнее цепочки if и явного приведения типов?
Что это: Оператор is в современном C# не только проверяет совместимость типов, но и извлекает значение в новую переменную (is Type variable) или сопоставляет структуру объекта через property patterns и relational patterns (>, <, and, or). Условие when добавляет произвольный предикат без второго if. Это заменяет связку as + null-check + cast одним безопасным выражением.
Почему важно: Это базовая концепция современного C#: без pattern matching код обработки разных типов разрастается вложенными if и небезопасными приведениями, а на собеседовании проверяют умение писать читаемую и безопасную ветвящуюся логику.
Под капотом: Компилятор Roslyn разворачивает is с pattern в последовательность проверок типа (isinst IL) и условных переходов. Для property patterns генерируется вызов геттеров и сравнение полей без рефлексии. В switch expression компилятор строит decision tree по типам и свойствам, что JIT может оптимизировать лучше, чем цепочку отдельных if с повторными приведениями.
Типичная ошибка: Разработчики продолжают писать if (obj is string) вместо if (obj is string s), получая лишнее приведение и риск InvalidCastException при параллельном изменении типа объекта между проверкой и cast.
object input = GetShape();
// Старый стиль: два шага — проверка и приведение
if (input is Circle)
{
var circle = (Circle)input;
Console.WriteLine(circle.Radius);
}
// Pattern matching: проверка, приведение и извлечение в одном выражении
if (input is Circle { Radius: > 0 and var r })
Console.WriteLine(r);