Разбираем Сопоставления по Шаблону в C#. Часть 3/5
Части 1, 2
Шаблоны отброса и var
Шаблон отброса (discard) _ соответствует чему угодно и ничего не связывает. Используйте его для варианта по умолчанию в операторе switch или в качестве заполнителя внутри других шаблонов, где не важна переменная. Одна особенность, которую стоит запомнить: в выражении switch допускается использование простого символа
_, но в выражении is или операторе switch его нужно писать как var _.Шаблон var соответствует чему угодно, включая null, и связывает найденное значение с новой переменной выведенного типа:
static void VarPattern() {
object o = null;
Assert.IsFalse(o is object);
Assert.IsTrue(o is var v); // var связывает даже null
}Кажется, что шаблон var почти никогда не подходит для использования в рабочем коде (напишите варианты в комментариях). Тот факт, что он соответствует
null, — это мина замедленного действия, и результирующая переменная находится в неопределённом состоянии. Возможный вариант использования разве что захват значений внутри других шаблонов, когда анонимные типы делают именование невозможным. Предпочтительнее использовать простое присваивание. Рецензентам не нужно запоминать, где шаблон var, а где объявление с выведением типа.Выражения switch
Возвращает значение. Преимущества по сравнению с классическим оператором switch - отсутствие ключевого слова case, оператора break, временной переменной для хранения результата и (самое главное) исчерпывающая проверка на этапе компиляции. Если компилятор доказывает, что некоторые входные данные не подходят ни под один случай в конце оператора switch, он выдаёт предупреждение. Выражения switch прекрасно сочетаются с членами-выражениями:
static string Describe(this Shape shape) =>
shape switch {
Circle c => $"форма – круг радиуса {c.Radius}",
Rectangle => "форма - прямоугольник ",
_ => "неизвестный вид формы "
};
Предостережение: выражения switch отлично смотрятся с 3 вариантами, но нечитаемы с 15ю. Вынесите логику в именованные вспомогательные методы или используйте оператор switch с явными блоками.
Шаблон свойств
Проверяет значения одного или нескольких свойств. В сочетании с шаблоном типа он проявляет себя наилучшим образом:
string whatShape = shape switch {
Circle { Radius: 1.0d } =>
"фигура – круг радиуса 1",
Rectangle r when r.Width == r.Height =>
"фигура - квадрат",
Rectangle { Width: 10d, Height: 5d} =>
"фигура – прямоугольник 10x5",
Rectangle { Width: var x, Height: var y } =>
$"фигура - прямоугольник {x}x{y} ",
{ } => "неизвестная фигура",
_ => "null"
};Несколько моментов:
- Использование
var внутри шаблона свойства — это законный вариант применения var. Здесь он захватывает значение свойства в локальную переменную.- Шаблон свойства требует, чтобы получатель был ненулевым. Поэтому пустые фигурные скобки в форме
{ } — проверка на ненулевое значение. Вы даже можете привязать этот шаблон в переменную - obj is { } notNull, чтобы получить ненулевую переменную без явного указания типа.Расширенный шаблон свойств
В C# 10 добавлена точечная нотация, сильно улучшившая читаемость:
// До
var shortNames = people
.Where(x => x is Person { FirstName: { Length: <= 5 } })
.Cast<Person>();
// после
var shortNames = people
.Where(x => x is Person { FirstName.Length: <= 5 })
.Cast<Person>();
Будьте аккуратны с количеством точек в цепочке. На 4-5й читаемость начинает страдать.
Продолжение следует…
Источник: https://blog.ndepend.com/c-pattern-matching-explained/