Что такое универсальное сопоставление с образцом в c # 7.1? - PullRequest
1 голос
/ 17 октября 2019

В C # 7.1 появилась новая функция, называемая общим сопоставлением с образцом. Один из найденных примеров выглядит следующим образом:

void Attack(IWeapon weapon, IEnemy enemy)
{
    switch (weapon)
    {
        case Sword sword:
            // process sword attack
            break;
        case Bow bow:
            // process bow attack
            break;
    }
}

Но, с моей точки зрения, это фрагмент неправильного дизайна, который нарушает второй принцип SOLID (open-close). Я даже не могу вспомнить случай, когда это могло бы понадобиться, насколько я понимаю, если вы попали в ситуацию, когда вам нужен такой переход, то вы делаете что-то очень неправильное. С другой стороны, если эта функция была добавлена ​​в язык, для этого должна быть веская причина. Так что вопрос в том, когда это понадобится, если вы не создаете плохую архитектуру.

Ответы [ 3 ]

1 голос
/ 17 октября 2019

A. Подобное switch может быть полезно, если вы не можете (иначе практически не просто ) изменять классы, с которыми вы работаете, например, Исключения.

B. сопоставление с образцом в switch может быть гораздо более сложным, чем просто различение типов.

Сопоставление с образцом от Что нового в C # 7.0 демонстрирует эту универсальность.

public static int SumPositiveNumbers(IEnumerable<object> sequence)
{
    int sum = 0;
    foreach (var i in sequence)
    {
        switch (i)
        {
            case 0:
                break;
            case IEnumerable<int> childSequence:
            {
                foreach(var item in childSequence)
                    sum += (item > 0) ? item : 0;
                break;
            }
            case int n when n > 0:
                sum += n;
                break;
            case null:
                throw new NullReferenceException("Null found in sequence");
            default:
                throw new InvalidOperationException("Unrecognized type");
        }
    }
    return sum;
}
0 голосов
/ 17 октября 2019

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

Однако, если Sword и Bow не зависят от класса, содержащего Attack метод, то у вас нет другого выбора. И для этого есть много примеров, таких как сериализация (как упоминалось в NibblyPig), но также и при создании уровня представления, ViewModel и т. Д. *

Если Sword и Bow не несут ответственностиобработки атаки (где релевантен SRP), и у вас есть определенный класс для этого случая, тогда вам придется переключаться между различными типами. Вы не хотите, чтобы у Sword был метод, который имеет дело с сериализацией, и метод, который имеет дело с тем, какой цвет будет Sword в одном конкретном меню и т. Д ...

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

Кроме того, иногда языковые функции могут помочь в работе с устаревшим кодом ине является показателем рекомендуемой передовой практики.

0 голосов
/ 17 октября 2019

Я согласен, что вы можете злоупотреблять им, чтобы нарушать открытое / закрытое, но вы не будете использовать его так, как вы использовали в своем примере (используя интерфейс).

Вместо этого рассмотрим ситуациюгде вы десериализуете объект.

У вас может быть программа чата, и люди могут отправлять сообщения или изображения (псевдокод)

Object myObject = (object) _network.Read().Deserialize();

if (myObject is IImage) { }
else if (myObject is ITextMessage) { }

Вместо этого вы можете поместить это в switch. Это все еще открыто закрыто, потому что вы можете написать дополнительные типы, которые расширяют IImage / ITextMessage.

Вы должны были бы изменить фундаментальные функциональные возможности программы, чтобы поддерживать вещи, которые не оба из них. Или вы могли бы иметь еще { doSomeDefaultBehaviour(); }

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...