В этой статье мы рассмотрим выражения Switch и сопоставление с образцом. Выражение Switch развивалось в течение нескольких версий, и в C # 8 оно значительно изменилось. В новом выражении switch значительно уменьшено количество повторяющихся ключевых слов case и break.

Давайте посмотрим как на традиционные, так и на новые выражения switch, чтобы понять изменения. Мы начнем с традиционного выражения следующим образом.

[pastacode lang=»c» manual=»%0A%20%20%20%20private%20static%20RGBColor%20ExecuteOldSwitch(PrimaryColor%20color)%20%20%0A%20%20%20%20%7B%20%20%0A%20%20%20%20%20%20%20switch%20(color)%20%20%0A%20%20%20%20%20%20%20%7B%20%20%0A%20%20%20%20%20%20%20%20%20%20case%20PrimaryColor.Red%3A%20%20%0A%20%20%20%20%20%20%20%20%20%20return%20new%20RGBColor(0xFF%2C%200×00%2C%200×00)%3B%20case%20PrimaryColor.Green%3A%20%20%0A%20%20%20%20%20%20%20%20%20%20return%20new%20RGBColor(0x00%2C%200xFF%2C%200×00)%3B%20case%20PrimaryColor.Blue%3A%20%20%0A%20%20%20%20%20%20%20%20%20%20return%20new%20RGBColor(0x00%2C%200×00%2C%200xFF)%3B%20default%3A%20%20%0A%20%20%20%20%20%20%20%20%20%20throw%20new%20ArgumentException(message%3A%20%22invalid%20color%22%2C%20paramName%3A%20nameof(color))%3B%20%20%0A%20%20%20%20%20%20%20%7D%3B%20%20%0A%20%20%20%20%7D%20%20%0A» message=»» highlight=»» provider=»manual»/]

Теперь давайте посмотрим на современный оператор switch, представленный в C #, следующим образом.

[pastacode lang=»c» manual=»%0A%20%20%20%20private%20static%20RGBColor%20ExecuteNewSwitch(PrimaryColor%20color)%20%3D%3E%20color%20switch%20%20%0A%20%20%20%20%7B%20%20%0A%20%20%20%20%20%20%20PrimaryColor.Red%20%3D%3E%20new%20RGBColor(0xFF%2C%200×00%2C%200×00)%2C%20PrimaryColor.Green%20%3D%3E%20new%20RGBColor(0x00%2C%200xFF%2C%200×00)%2C%20PrimaryColor.Blue%20%3D%3E%20new%20RGBColor(0x00%2C%200×00%2C%200xFF)%2C%20%20%0A%20%20%20%20%20%20%20_%20%3D%3E%20throw%20new%20ArgumentException(message%3A%20%22invalid%20color%22%2C%20paramName%3A%20nameof(color))%20%20%0A%20%20%20%20%7D%3B%20%20%0A» message=»» highlight=»» provider=»manual»/]

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

  • Имя переменной ставится перед переключателем.
  • Элементы case и: заменяются на =>.
  • default был заменен на _ .
  • Параметры — это больше не утверждения, а выражения.

Из новых операторов switch появились некоторые дополнительные шаблоны, такие как шаблоны свойств, кортежей и позиций. Давайте посмотрим на них по очереди.

Шаблон свойств

Шаблон свойств помогает сравнивать свойства объекта.

Рассмотрим сайт расчета государственных налогов, который должен рассчитывать налог на основе адреса покупателя. В этом случае размер налога зависит от государственной собственности адреса. В следующем примере используется шаблон свойства для вычисления налога с адреса вместе с общей ценой.

[pastacode lang=»c» manual=»%0A%20%20%20%20public%20static%20void%20ExecutePropertyPattern()%20%20%0A%20%20%20%20%7B%20%20%0A%20%20%20%20%20%20%20Address%20address%20%3D%20new%20Address%7B%20State%20%3D%20%22MN%22%7D%3B%20Console.WriteLine(%24%22Overall%20price%20(including%20tax)%20of%20%20%0A%20%20%20%20%20%20%20%7Baddress.State%7D%20is%3A%20%7BComputeOverallPrice(address%2C%202.4M)%7D%22)%3B%20%20%0A%20%20%20%20%7D%20%20%0A%20%20%20%20private%20static%20decimal%20ComputeOverallPrice(Address%20location%2C%20decimal%20price)%20%20%0A%20%20%20%20%3D%3E%20%20%0A%20%20%20%20location%20switch%20%20%0A%20%20%20%20%7B%20%20%0A%20%20%20%20%20%20%20%7B%20State%3A%20%22MN%22%20%7D%20%3D%3E%20price%20%2B%20price%20*%200.78M%2C%20%20%0A%20%20%20%20%20%20%20%7B%20State%3A%20%22MI%22%20%7D%20%3D%3E%20price%20%2B%20price%20*%200.06M%2C%20%20%0A%20%20%20%20%20%20%20%7B%20State%3A%20%22WA%22%20%7D%20%3D%3E%20price%20%2B%20price%20*%200.07M%2C%20%20%0A%20%20%20%20%20%20%20_%20%3D%3E%200M%20%20%0A%20%20%20%20%7D%3B%20%20%0A» message=»» highlight=»» provider=»manual»/]

Шаблон кортежа

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

Давайте посмотрим на пример следующим образом.

[pastacode lang=»c» manual=»%0A%20%20%20%20public%20static%20void%20ExecuteTuplePattern()%20%20%0A%20%20%20%20%7B%20%20%0A%20%20%20%20%20%20%20(string%2C%20string%2C%20string)%20counties%20%3D%20(%22India%22%2C%20%22Australia%22%2C%22England%22)%3B%20%20%0A%20%20%20%20%20%20%0A%20%20%20%20%20%20%20var%20team1%20%3D%20counties.Item1.ToString()%3B%20%20%20%0A%20%20%20%20%20%20%20var%20team2%20%3D%20counties.Item3.ToString()%3B%20%20%0A%20%20%20%20%20%20%20Console.WriteLine(%24%22Result%20of%20the%20match%20between%20%7Bteam1%7D%20and%20%7Bteam2%7D%20is%3A%20%7BReturnWinner(team1%2C%20team2)%7D%22)%3B%20%20%0A%20%20%20%20%7D%20%20%0A%20%20%20%20%20%20%0A%20%20%20%20private%20static%20string%20ReturnWinner(string%20team1%2C%20string%20team2)%20%20%0A%20%20%20%20%3D%3E%20(team1%2C%20team2)%20switch%20%20%0A%20%20%20%20%7B%20%20%0A%20%20%20%20%20%20%20(%22India%22%2C%20%22Australia%22)%20%3D%3E%20%22Australia%20is%20covered%20by%20India.%20India%20wins.%22%2C%20%20%0A%20%20%20%20%20%20%20(%22Australia%22%2C%20%22England%22)%20%3D%3E%20%22Australia%20breaks%20England.%20Australia%20wins.%22%2C%20%20%0A%20%20%20%20%20%20%20(%22India%22%2C%20%22England%22)%20%3D%3E%20%22India%20covers%20England.%20India%20wins.%22%2C%20%20%0A%20%20%20%20%20%20%20(_%2C%20_)%20%3D%3E%20%22tie%22%20%20%0A%20%20%20%20%7D%3B%20%20%0A» message=»» highlight=»» provider=»manual»/]

Как вы можете видеть в приведенном выше коде, значение кортежа сравнивается, а выражение соответствующего значения кортежа возвращается вызывающей стороне. В приведенном выше примере результат будет отображаться как «Результат матча между Индией и Англией: Индия покрывает Англию. Индия побеждает».

Позиционный шаблон

Помимо свойств и кортежей, шаблоны могут совпадать даже по позициям. Сопоставление с позиционным образцом работает с помощью деконструктора, представленного в C # 7.

Деконструктор позволяет устанавливать свои свойства в дискретные переменные и позволяет компактно использовать позиционные шаблоны без необходимости называть свойства.

Давайте рассмотрим пример, чтобы лучше понять это. Для начала создадим класс Point, который использует метод deconstruct.

[pastacode lang=»c» manual=»%0A%20%20%20%20public%20class%20Point%20%20%0A%20%20%20%20%7B%20%20%0A%20%20%20%20%20%20%20public%20int%20X%20%7B%20get%3B%20%7D%20public%20int%20Y%20%7B%20get%3B%20%7D%20%20%0A%20%20%20%20%20%20%20public%20Point(int%20x%2C%20int%20y)%20%3D%3E%20(X%2C%20Y)%20%3D%20(x%2C%20y)%3B%20public%20void%20Deconstruct(out%20int%20x%2C%20out%20int%20y)%20%20%0A%20%20%20%20%20%20%20%7B%20%20%0A%20%20%20%20%20%20%20%20%20%20(x%2C%20y)%20%3D%20(X%2C%20Y)%3B%20%20%0A%20%20%20%20%20%20%20%7D%20%20%0A%20%20%20%20%7D%20%20%0A» message=»» highlight=»» provider=»manual»/]

Обратите внимание, что здесь имя метода Deconstruct требуется компилятору, и любое другое имя с таким же телом метода не будет работать.

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

[pastacode lang=»c» manual=»%0A%20%20%20%20public%20enum%20Quadrant%20%20%0A%20%20%20%20%7B%20%20%0A%20%20%20%20%20%20%20Origin%2C%20One%2C%20%20%20%0A%20%20%20%20%20%20%20Two%2C%20Three%2C%20Four%2C%20%20%0A%20%20%20%20%20%20%20OnBorder%2C%20Unknown%20%20%0A%20%20%20%20%7D%20%20%0A» message=»» highlight=»» provider=»manual»/]

Теперь у нас есть логика для поиска шаблонов и метод для их вызова и печати на консоли.

[pastacode lang=»c» manual=»public%20static%20void%20ExecutePositionalPattern()%20%20%0A%7B%20%20%0A%20%20%20Point%20point%20%3D%20new%20Point(5%2C10)%3B%20%20%0A%20%20%20Console.WriteLine(%24%22Quadrant%20of%20point%20%7Bpoint.X%7D%20and%20%7Bpoint.Y%7D%20is%3A%20%7BFindQuadrant(point)%7D%22)%3B%20%20%0A%7D%20%20%0A%20%20%0Aprivate%20static%20Quadrant%20FindQuadrant(Point%20point)%20%3D%3E%20point%20switch%20%20%0A%7B%20%20%0A%20%20%20(0%2C%200)%20%3D%3E%20Quadrant.Origin%2C%20%20%0A%20%20%20var%20(x%2C%20y)%20%20when%20%20%20%20x%20%20%20%3E%20%20%20%200%20%20%20%26%26%20%20y%20%20%20%3E%20%20%20%200%20%20%20%3D%3E%20%20%20Quadrant.One%2C%20%20%0A%20%20%20var%20(x%2C%20y)%20%20when%20%20%20%20x%20%20%20%3C%20%20%20%200%20%20%20%26%26%20%20y%20%20%20%3E%20%20%20%200%20%20%20%3D%3E%20%20%20Quadrant.Two%2C%20%20%0A%20%20%20var%20(x%2C%20y)%20%20when%20%20%20%20x%20%20%20%3C%20%20%20%200%20%20%20%26%26%20%20y%20%20%20%3C%20%20%20%200%20%20%20%3D%3E%20%20%20Quadrant.Three%2C%20%20%0A%20%20%20var%20(x%2C%20y)%20%20when%20%20%20%20x%20%20%20%3E%20%20%20%200%20%20%20%26%26%20%20y%20%20%20%3C%20%20%20%200%20%20%20%3D%3E%20%20%20Quadrant.Four%2C%20%20%0A%20%20%20var%20(_%2C%20_)%20%3D%3E%20Quadrant.OnBorder%2C%20%20%0A%20%20%20_%20%3D%3E%20Quadrant.Unknown%20%20%0A%7D%3B%20″ message=»» highlight=»» provider=»manual»/]

Приведенный выше код будет выводиться как «Квадрант точек 5 и 10 равен: Один», поскольку пройденные точки 5 и 10 попадают в первый квадрант.

В приведенном выше коде шаблон отбрасывания (_) соответствует, когда либо x, либо y равно 0, но не оба. Важным моментом в выражении switch является то, что оно должно либо выдавать значение при совпадении вариантов, либо выдавать исключение, если ни один из вариантов не соответствует. Кроме того, компилятор выдает предупреждение, если вы не включили все возможные случаи в выражение переключения.

Примечание

Деконструкция — не лучший выбор, и ее следует использовать только для тех типов, где она имеет смысл и понятнее для интерпретации. Например, для класса Point было легко и интуитивно понятно предположить, что первое значение — X, а второе — Y, поэтому внимательно используйте позиционные шаблоны.

Резюме

В этой статье мы рассмотрели новый синтаксис переключателя и сравнили его с традиционным. Мы также поняли, как шаблоны (свойство, кортеж и позиционирование) можно использовать с переключателем, чтобы сделать его еще более мощным. Совершенно очевидно, что новый синтаксис переключателя более четкий и простой в использовании.