web-dev-qa-db-ja.com

C#で始まるスイッチケース文字列

文字列が何かで始まるかどうかを言うswitchステートメントでcase条件を作成する方法はありますか?

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

[〜#〜] update [〜#〜]他の文字列は異なる長さにすることができます。

abc ..

abczyv

dcs2。

qwerty

as ... k

41
Amra

気になる条件の長さがすべて同じ長さであることがわかっている場合は、次のことができます。

_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文字の文字列の束と3文字の文字列の束。2文字比較の一致の後に3文字比較が続きます。ただし、そのような文字列が非常に多い場合を除き、実行中のコードとそれを維持する必要のある人の両方の単純なif-elseチェーンよりもすぐに効率が低下します。

編集:異なる長さになると述べたので追加しました。最初のX文字をチェックしてから次のY文字をチェックするなどのパターンを実行できますが、ほとんどの文字列が同じ長さであるパターンがない限り、これは維持するのが非効率的で恐ろしいことです(古典的な場合早すぎる悲観の)。

コマンドパターンは別の回答で言及されているので、文字列パターンをIDにマップする場合と同様に、その詳細は説明しませんが、オプションです。

If-elseチェーンからコマンドまたはマッピングパターンに変更して効率スイッチを取得することはありません時々がif-elseを超えるため、コマンドの比較やIDパターンの取得がさらに失われます。ただし、コードが明確になった場合はそうします。

If-elseのチェーンは、文字列比較または正規表現(これまでの接頭辞一致よりも複雑な比較がある場合、後者はおそらくより簡単で高速になるでしょう)のどちらかで、かなりうまく機能します。 exは、この種のパターンのより一般的なケースで時々うまく機能するからです。

If-elsesを使用する場合、どのケースが最も頻繁に発生するかを検討し、あまり一般的でないケースのテストの前にそれらのテストを実行するようにしてください(もちろん、「abcdで始まる」が検索の場合「abcで始まる」前にチェックする必要があります)。

38
Jon Hanna

短い答え:いいえ。

Switchステートメントは、一度だけ評価される式を取ります。結果に基づいて、別のコードが実行されます。

だから何? => String.StartsWithは関数です。指定されたパラメーターと一緒に、それは式です。ただし、ケースの場合は、ケースごとに異なるパラメーターを渡す必要があるため、一度だけ評価することはできません。

長い答え#1は他の人から与えられました。

長い答え#2:

達成しようとしているものに応じて、コマンドパターン / チェーンの責任パターン。ケースに適用すると、各コードはCommandの実装によって表されます。 executeメソッドに加えて、コマンドはブールAcceptメソッドを提供できます。このメソッドは、指定された文字列がそれぞれのパラメータ。

利点:ハードコードされた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");
    }
}    
13
chiccodoro

すべてのケースの長さが同じ場合、使用できます
switch (mystring.SubString(0,Math.Min(len, mystring.Length)))
別のオプションは、文字列に基づいてcategoryIdを返し、idをオンにする関数を使用することです。

5
Itay Karo

これは、C#7.0のパターンマッチングで可能になりました。例えば:

var myString = "abcDEF";

switch(myString)
{
    case string x when x.StartsWith("abc"):
        //Do something here
        break;
}
4
Raúl Bojalil

問題のあるドメインに何らかの文字列ヘッダーの概念がある場合、これは列挙型としてモデル化できます。

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

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

enum StringHeader { ABC, QWERTY, ... }
3
Felix Ungman

部分文字列の回答に加えて、mystring.SubString(0,3)としてそれを実行し、「abc」かどうかをcaseステートメントでチェックできます。

ただし、switchステートメントの前に、mystringの長さが少なくとも3であることを確認する必要があります。

1
Sachin Shanbhag