C # Строка переключателя, начинающаяся с - PullRequest
41 голосов
/ 04 октября 2010

Есть ли способ создать условие 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.

* 1016 QWERTY *

, как ... к

Ответы [ 7 ]

38 голосов
/ 04 октября 2010

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

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 символов не вызывала исключение при операции с подстрокой.

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

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

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

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

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

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

13 голосов
/ 04 октября 2010

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

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

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

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

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

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

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

Пример, приведенный в вашем вопросе, будет выглядеть так:

5 голосов
/ 04 октября 2010

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

3 голосов
/ 04 октября 2010

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

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

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

enum StringHeader { ABC, QWERTY, ... }
2 голосов
/ 24 октября 2018

Это теперь возможно при сопоставлении с образцом в C # 7.0. Например:

var myString = "abcDEF";

switch(myString)
{
    case string x when x.StartsWith("abc"):
        //Do something here
        break;
}
1 голос
/ 04 октября 2010

В дополнение к ответу на подстроку, вы можете сделать это как mystring.SubString (0,3) и проверить в операторе case, не является ли его «abc».Длина mystring не менее 3-х.

0 голосов
/ 18 мая 2013

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

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

Switch(value)
{
    Case "abc":

    break;

    default:

    break;
}       
...