Что произойдет, если мое выражение переключателя C# не является исчерпывающим?

В C# 8 были введены выражения переключения. Что происходит, если выражение switch не является исчерпывающим? Другими словами, что произойдет, если я не проверю все возможные значения?

    static void Main(string[] args)
    {
        int x = 1;
        int imExhaustive = x switch
        {
            3 => 4,
            _ => 0   // x = 1 matches this
        };
        int okFine = x switch
        {
            1 => 4   // x = 1 matches this
        };
        int noMatch = x switch
        {
            3 => 4   // No match
        };
    }

4 ответа

Если switch выражение не является исчерпывающим, компилятор выдает предупреждение. Во время выполнения, если вы передаете значение, которое не обрабатывается, SwitchExpressionException брошен

Это описано в спецификации для новых шаблонов в C# 8.0: https://github.com/dotnet/csharplang/blob/master/proposals/csharp-8.0/patterns.md#switch-expression

Компилятор должен выдать предупреждение, если он доказывает (используя эти методы), что некоторое возможное входное значение может не совпадать с некоторым switch_expression_arm во время выполнения.

Во время выполнения результатом switch_expression является значение выражения первого switch_expression_arm, для которого выражение слева от switch_expression соответствует шаблону switch_expression_arm, и для которого case_guard switch_expression_arm, если имеется, оценивает к истине.

Если такого switch_expression_arm нет, switch_expression генерирует экземпляр исключения System.Runtime.CompilerServices.SwitchExpressionException.

Зависит.

Если есть совпадение: оно совпадает, и все хорошо.

Если нет совпадений: A SwitchExpressionException брошен

Лучше всего писать исчерпывающие выражения переключателей. Если нет, и ничего не взрывается, возможно, вам просто повезло.

Компилятор предупредит вас, если ваше выражение switch не является исчерпывающим, но это не ошибка, и он все равно скомпилируется и запустится.

(Просто наткнулся на это, поэтому подумал, что поделюсь - пока нигде в документации нет, хотя C# 8 все еще в Preview)

Чтобы удалить это предупреждение, добавьте выражение по умолчанию.

         exception switch
    {
        ValidationException vExp => new ValidationErrorDetail
        {
            
        },
        ApiException apiExp => new ApiErrorDetail
        {
           
        },
        ProcessException pExp => new ErrorDetail
        {
           
        },
        _ => new ErrorDetail
        {

        }
    };

Добавлять _ =>и Выражение по умолчанию для выполнения.

В случае безымянных значений перечисления я считаю поведение C# по выбрасыванию исключений правильным и желательным. Поэтому я отключаю предупреждение в своем .editorconfig:

      [*.cs]
dotnet_diagnostic.CS8524.severity = none # The switch expression does not handle some values of its input type (it is not exhaustive) involving an unnamed enum value.
Другие вопросы по тегам