C# Switch-case строка, начинающаяся с

есть ли способ, чтобы сделать условие case в операторе switch, где вы говорите, если строка начинается с чего-то?

ex

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;
}

обновление Другие строки могут быть разной длины.

abc..

abczyv

dcs2.

qwerty

as...k

6 ответов


Если бы вы знали, что длина условий, о которых вы заботитесь, будет одинаковой, вы могли бы:

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 как для запущенного кода, так и для человека, который должен его поддерживать.

Edit: добавлено, так как вы теперь заявили, что они будут разной длины. Вы можете сделать шаблон, о котором я упоминал, проверяя первые символы X, а затем следующие символы Y и так далее, но если нет шаблона, где большинство строк имеют одинаковую длину, это будет неэффективно и ужасно поддерживать (классический случай преждевременной pessimisation).

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

Я бы не менял цепочки if-else на команды или шаблоны отображения, чтобы получить переключатель эффективности иногда имеет над if-else, так как вы теряете больше в сравнениях для команды или получения шаблона ID. Я бы сделал это, если бы он сделал код более ясный.

цепочка if-else может работать довольно хорошо, либо со строковыми сравнениями, либо с регулярными выражениями (последнее, если у вас есть сравнения более сложные, чем префикс-совпадения до сих пор, что, вероятно, было бы проще и быстрее, я упоминаю reg-ex только потому, что они иногда хорошо работают с более общими случаями такого рода шаблона).

Если вы идете на if-elses, попробуйте рассмотреть, какие случаи будут происходить чаще всего, и сделать эти тесты это происходит раньше, чем для менее распространенных случаев (хотя, конечно, если "начинается с abcd" - это случай, который нужно искать, его нужно будет проверить перед "начинается с abc").


короткий ответ: Нет.

оператор switch принимает выражение, которое вычисляется только один раз. На основе результата выполняется другой фрагмент кода.

ну и что? => Строка.StartsWith-это функция. Вместе с заданным параметром это выражение. Однако для вашего случая вам нужно передать другой параметр для каждого случая, поэтому его нельзя оценить только один раз.

длинный ответ #1 был дан другими.

длинный ответ #2:

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

преимущество: вместо вашего жестко закодированного оператора switch, жестко закодированных оценок 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");
    }
}    

Если все случаи имеют одинаковую длину, вы можете использовать
switch (mystring.SubString(0,Math.Min(len, mystring.Length))).
Другой вариант - иметь функцию, которая будет возвращать categoryId на основе строки и переключаться на id.


если проблемный домен имеет какую-то концепцию заголовка строки, это может быть смоделировано как перечисление.

switch(GetStringHeader(s))
{
    case StringHeader.ABC: ...
    case StringHeader.QWERTY: ...
    ...
}

StringHeader GetStringHeader(string s)
{
    if (s.StartsWith("ABC")) return StringHeader.ABC;
    ...
}

enum StringHeader { ABC, QWERTY, ... }

в дополнение к ответу подстроки, вы можете сделать это как mystring.Подстрока (0,3) и проверка в операторе case, если его "abc".

но перед инструкцией switch вам нужно убедиться, что ваша mystring по крайней мере 3 в длину.


попробуйте это и скажите мне, если это работает, надеюсь это поможет вам:

string value = Convert.ToString(Console.ReadLine());

Switch(value)
{
    Case "abc":

    break;

    default:

    break;
}