Как вы, похоже, знаете, нижний регистр двух строк и сравнение их - это не то же самое, что сравнение без учета регистра. Есть много причин для этого. Например, стандарт Unicode позволяет кодировать текст с диакритическими знаками несколькими способами. Некоторые символы включают в себя как базовый, так и диакритический знак в одной кодовой точке. Эти символы также могут быть представлены как базовый символ, за которым следует объединенный диакритический знак. Эти два представления одинаковы для всех целей, и сопоставления строк с учетом культуры в .NET Framework правильно идентифицируют их как равные как с CurrentCulture, так и с InvariantCulture (с IgnoreCase или без него). Порядковое сравнение, с другой стороны, неверно расценивает их как неравные.
К сожалению, switch
не делает ничего, кроме порядкового сравнения. Порядковое сравнение подходит для определенных видов приложений, таких как анализ файла ASCII со строго определенными кодами, но сравнение порядковых строк не подходит для большинства других применений.
То, что я делал в прошлом, чтобы получить правильное поведение, это просто макет моего собственного оператора switch. Есть много способов сделать это. Один из способов - создать List<T>
пар строк и делегатов. Список можно искать, используя правильное сравнение строк. Когда совпадение найдено, может быть вызван связанный с ним делегат.
Другой вариант - создать очевидную цепочку if
операторов. Обычно это оказывается не так плохо, как кажется, поскольку структура очень правильная.
Самое замечательное в этом то, что на самом деле нет никакой потери производительности при моделировании ваших собственных функций коммутатора при сравнении со строками. Система не собирается составлять таблицу переходов O (1) так, как это может быть с целыми числами, поэтому она все равно будет сравнивать каждую строку по одной за раз.
Если нужно сравнить множество случаев, и производительность является проблемой, то описанную выше опцию List<T>
можно заменить отсортированным словарем или хэш-таблицей. Тогда производительность может потенциально соответствовать или превышать опцию оператора switch.
Вот пример списка делегатов:
delegate void CustomSwitchDestination();
List<KeyValuePair<string, CustomSwitchDestination>> customSwitchList;
CustomSwitchDestination defaultSwitchDestination = new CustomSwitchDestination(NoMatchFound);
void CustomSwitch(string value)
{
foreach (var switchOption in customSwitchList)
if (switchOption.Key.Equals(value, StringComparison.InvariantCultureIgnoreCase))
{
switchOption.Value.Invoke();
return;
}
defaultSwitchDestination.Invoke();
}
Конечно, вы, вероятно, захотите добавить некоторые стандартные параметры и, возможно, тип возврата к делегату CustomSwitchDestination. И вы захотите сделать лучшие имена!
Если поведение каждого из ваших дел не поддается делегированию вызова таким образом, например, если необходимы разные параметры, то вы застряли с цепочечными if
утверждениями. Я также делал это несколько раз.
if (s.Equals("house", StringComparison.InvariantCultureIgnoreCase))
{
s = "window";
}
else if (s.Equals("business", StringComparison.InvariantCultureIgnoreCase))
{
s = "really big window";
}
else if (s.Equals("school", StringComparison.InvariantCultureIgnoreCase))
{
s = "broken window";
}