С# Строка переключателя, начиная с
Есть ли способ сделать условие case в инструкции switch, где вы говорите, что строка начинается с чего-то?
ех
Switch (mystring)
{
case("abc")://String begins with abc (abcd or abc1 or abcz or abc.. or abc will fall in this condition).
//Do Something
break;
default:
break;
}
UPDATE
Другие строки могут иметь разную длину.
а..
abczyv
DCS2.
QWERTY
как... к
Ответы
Ответ 1
Если бы вы знали, что длина условий, о которых вы бы позаботились, была бы одинаковой длины, вы могли бы:
switch(mystring.substring(0, Math.Min(3, mystring.Length))
{
case "abc":
//do something
break;
case "xyz":
//do something else
break;
default:
//do a different thing
break;
}
Math.Min(3, mystring.Length)
существует так, что строка из менее 3 символов не будет генерировать исключение в операции подстроки.
Существуют расширения этого метода для соответствия, например. набор строк 2 char и набор строк 3 char, где после сопоставления сравнений 2- char следуют сравнения 3 char. Если у вас не очень большое количество таких строк, это быстро становится менее эффективным, чем простая цепочка if-else как для исполняемого кода, так и для человека, который должен его поддерживать.
Изменить: добавлено, поскольку вы уже заявили, что они будут иметь разную длину. Вы могли бы сделать шаблон, который я упомянул, проверяя первые X-символы, а затем следующие Y-символы и т.д., Но если нет шаблона, в котором большая часть строк имеет одинаковую длину, это будет неэффективным и ужасным для поддержания (классический случай преждевременной пессимизации).
Шаблон команды упоминается в другом ответе, поэтому я не буду подробно описывать это, так же как и то, где вы сопоставляете строковые шаблоны с идентификаторами, но они являются опцией.
Я бы не изменился с цепей if-else на команды или шаблоны сопоставления, чтобы получить переключатель эффективности иногда имеет более if-else, поскольку вы теряете больше в сравнении для команды или получаете идентификатор шаблон. Я бы сделал это, если бы сделал код более понятным.
Цепочка if-else может работать очень хорошо, либо с помощью сравнения строк, либо с регулярными выражениями (последняя, если у вас есть сравнения, более сложные, чем префикс-матчи до сих пор, что, вероятно, было бы проще и быстрее, я упоминание reg-ex только потому, что они иногда хорошо работают с более общими случаями такого рода шаблонов).
Если вы идете на if-elses, попробуйте рассмотреть, какие случаи будут происходить чаще всего, и сделайте эти тесты до тех, которые для менее распространенных случаев (хотя, конечно, если "начинается с abcd", это случай, чтобы посмотреть потому что его нужно было бы проверить до того, как "начнется с abc" ).
Ответ 2
Короткий ответ: Нет.
Оператор switch принимает выражение, которое оценивается только один раз. На основе результата выполняется другой фрагмент кода.
И что? = > String.StartsWith является функцией. Вместе с заданным параметром это выражение. Однако для вашего случая вам нужно передать другой параметр для каждого случая, поэтому его нельзя оценить только один раз.
Длинный ответ # 1 был предоставлен другими.
Длинный ответ # 2:
В зависимости от того, чего вы пытаетесь достичь, вас может заинтересовать Command Pattern/Шаблон цепочки ответственности. Применительно к вашему делу каждый фрагмент кода будет представлен реализацией команды. В дополнение к методу execute, команда может предоставить логический метод Accept, который проверяет, начинается ли заданная строка с соответствующим параметром.
Преимущество: вместо жесткого закодированного оператора switch, hardcoded StartsWith с оценками и жестко закодированными строками, у вас будет гораздо больше гибкости.
Пример, который вы дали в своем вопросе, будет выглядеть следующим образом:
var commandList = new List<Command>() { new MyABCCommand() };
foreach (Command c in commandList)
{
if (c.Accept(mystring))
{
c.Execute(mystring);
break;
}
}
class MyABCCommand : Command
{
override bool Accept(string mystring)
{
return mystring.StartsWith("abc");
}
}
Ответ 3
Если все случаи имеют одинаковую длину, вы можете использовать
switch (mystring.SubString(0,Math.Min(len, mystring.Length)))
.
Другой вариант - иметь функцию, которая вернет categoryId на основе строки и включит идентификатор.
Ответ 4
Если проблемная область имеет некоторую концепцию заголовка строки, это может быть смоделировано как перечисление.
switch(GetStringHeader(s))
{
case StringHeader.ABC: ...
case StringHeader.QWERTY: ...
...
}
StringHeader GetStringHeader(string s)
{
if (s.StartsWith("ABC")) return StringHeader.ABC;
...
}
enum StringHeader { ABC, QWERTY, ... }
Ответ 5
В дополнение к ответу подстроки вы можете сделать это как mystring.SubString(0,3) и проверить регистр case, если его "abc".
Но перед оператором switch вам нужно убедиться, что ваш мистик по крайней мере 3 дюйма.
Ответ 6
Попробуйте это и сообщите мне, если он работает, надеюсь, что он вам поможет:
string value = Convert.ToString(Console.ReadLine());
Switch(value)
{
Case "abc":
break;
default:
break;
}