Регистронезависимый switch

127
29 ноября 2019, 01:50

Есть у меня фрагмент кода в котором я хочу заменить if на switch:

if( request.SomeParam.Equals("Something1", StringComparison.InvariantCultureIgnoreCase))
{
    Execute1();
}
if (request.SomeParam.Equals("Something2", StringComparison.InvariantCultureIgnoreCase))
{
    Execute2();
}
throw new ArgumentOutOfRangeException(nameof(Request.Param));

Однако параметры регистронезависимые и придётся в case вписывать строки приведённые к нижнему регистру, что приведёт к понижению читаемости, т.к. в реальности "Something1" это достаточно длинная строка SomethingAndSomething и её визуально проще видеть именно так, а не искать границы слов в somethingandsomething.

Я пока пришёл к варианту:

const string SomethingAndSomething = "SomethingAndSomething";
const string SomethingOrSomething = "SomethingOrSomething";
switch(request.SomeParam.ToLowerInvariant())
{
    case SomethingAndSomething.ToLowerInvariant():
        Execute1();
        break;
    case SomethingOrSomething.ToLowerInvariant():
        Execute2();
        break;
    default:
        throw new ArgumentOutOfRangeException(nameof(Request.Param));
}

Но не очень нравится это повторяющаяся мантра .ToLowerInvariant(), может быть есть какие-то ещё более удачные варианты рефакторинга?

Версия C# 7.0, т.е. есть возможность использовать и новые фичи языка.

Answer 1
const string SomethingAndSomething = "somethingandsomething";
const string SomethingOrSomething = "somethingorsomething";
const string someParamToLower = request.SomeParam.ToLowerInvariant();
switch(someParamToLower)
{
    case SomethingAndSomething:
        Execute1();
        break;
    case SomethingOrSomething:
        Execute2();
        break;
    default:
        throw new ArgumentOutOfRangeException(nameof(Request.Param));
}

так?

Answer 2

Вместо приведения каждого из вариантов к Lower ты можешь привести только проверяемую часть к ловер или к аппер.

А в кейс сразу передавать надписи нужного регистра. И в таком случае будет приведение только в switch-е а не в каждом из кейсов.

Answer 3

Можно использовать pattern matching. Он доступен начиная с версии C# 7.0.

string someParam = "somethingorsomething";
switch (someParam)
{
    case var param
    when param.Equals("SomethingAndSomething", StringComparison.InvariantCultureIgnoreCase):
        Console.WriteLine("and");
        break;
    case var param
    when param.Equals("SomethingOrSomething", StringComparison.InvariantCultureIgnoreCase):
        Console.WriteLine("or");
        break;
    default:
        throw new ArgumentOutOfRangeException("error");
}

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

READ ALSO
Реализация превью чужого окна

Реализация превью чужого окна

Как реализовать превью чужих окон в своём окне? Аналогично нажатию alt+tab

96
Ошибка миграции There is already an object named 'Permission' in the database

Ошибка миграции There is already an object named 'Permission' in the database

Не понимаю, постоянно ловлю ошибки например

123
Обновление Chart в отдельном потоке

Обновление Chart в отдельном потоке

На форме имеется 5 элементов chart, их нужно обновлять каждый определённый промежуток времени, при этом ,чтобы в этот момент с окном программы...

116