Выражение вложенного переключателя - PullRequest
1 голос
/ 04 мая 2020

У меня есть следующее утверждение с использованием выражения-переключателя:

var levelType = task switch
{
    var t when t.Status == TaskStatus.EXECUTING && t.PlanIDs.Contains(currentPlan.ID) => WorkplaceAssociatedLevelTypes.Critical,
    var t when t.Status == TaskStatus.WAITING && t.PlanIDs.Contains(currentPlan.ID) => WorkplaceAssociatedLevelTypes.Warning,
    _ => WorkplaceAssociatedLevelTypes.Untyped
};

Как мы видим, t.PlanIDs.Contains(currentPlan.ID) повторяется дважды, и я бы хотел этого избежать.

Я не уверен если возможно сделать вложенный оператор с помощью выражения switch.

Примерно так:

var levelType = task switch
{
    case (task.PlanIDs.Contains(currentPlan.ID))
      true: 
        var t when t.Status == TaskStatus.EXECUTING => WorkplaceAssociatedLevelTypes.Critical,
        var t when t.Status == TaskStatus.WAITING => WorkplaceAssociatedLevelTypes.Warning,
        _ => WorkplaceAssociatedLevelTypes.Untyped
      false: WorkplaceAssociatedLevelTypes.Untyped
};

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

Использование if-else работает:

var levelType = WorkplaceAssociatedLevelTypes.Untyped;

    if (task.PlanIDs.Contains(currentPlan.ID))
    {
        if (task.Status == TaskStatus.EXECUTING)
        {
            levelType = WorkplaceAssociatedLevelTypes.Critical;
        }
        else if (task.Status == TaskStatus.WAITING)
        {
            levelType = WorkplaceAssociatedLevelTypes.Warning;
        }
    }

Ответы [ 2 ]

2 голосов
/ 04 мая 2020

Синтаксис выражения switch не меняется только потому, что вы хотите их вложить, он одинаков до конца.

([expr] switch {
    [case] => [expr],
})

([expr] switch {
    [case] => ([expr] switch {
        [case] => [expr]
    }),
})

В вашем случае:

var levelType = task.PlanIDs.Contains(currentPlan.ID) switch
{
    true => t.Status switch
    {
        TaskStatus.EXECUTING => WorkplaceAssociatedLevelTypes.Critical,
        TaskStatus.WAITING => WorkplaceAssociatedLevelTypes.Warning,
        _ => WorkplaceAssociatedLevelTypes.Untyped,
    },
    _ => WorkplaceAssociatedLevelTypes.Untyped,
};

Хотя вы, вероятно, могли бы просто использовать одно выражение переключателя с этим:

var levelType = task.Status switch
{
    // cases are evaluated in the order they are given
    _ when !task.PlanIDs.Contains(currentPlan.ID) => WorkplaceAssociatedLevelTypes.Untyped,
    TaskStatus.EXECUTING => WorkplaceAssociatedLevelTypes.Critical,
    TaskStatus.WAITING => WorkplaceAssociatedLevelTypes.Warning,
    _ => WorkplaceAssociatedLevelTypes.Untyped,
};

Учитывая, что вы работаете с логическим выражением, я мог бы вместо этого использовать условное выражение:

var levelType = task.PlanIDs.Contains(currentPlan.ID)
    ? task.Status switch
    {
        TaskStatus.EXECUTING => WorkplaceAssociatedLevelTypes.Critical,
        TaskStatus.WAITING => WorkplaceAssociatedLevelTypes.Warning,
        _ => WorkplaceAssociatedLevelTypes.Untyped,
    }
    : WorkplaceAssociatedLevelTypes.Untyped;
1 голос
/ 04 мая 2020

Я думаю, что в первую очередь настало время для разгона скорости: https://ericlippert.com/2012/12/17/performance-rant/

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

Оптимизация, не колеблясь, превращает действительно короткий переключатель / случай во вложенный if-else, например. И JiT может даже решить, что этот случай случается так часто, что дешевле просто написать bool temp = t.PlanIDs.Contains(currentPlan.ID) перед переключателем / кейсом.

Практическое решение: вы всегда можете заменить переключатель / регистр со словарем или наоборот. Скажем, Dictionary<SpecialFoldersEnumeration, Action>, обработанный al oop, будет таким же действительным, как код / ​​переключатель, закодированный для каждого значения перечисления, о котором вы заботитесь.

Но поскольку вы делаете сложные проверки, 1-й тип должен, вероятно, делегат, который возвращает bool и принимает t в качестве аргумента.

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