2017-06-04 12 views
3

新しいタプルの値の型を使用しています。この例では、1つまたは複数のタプルのケースについてswitch文を作成しようとしています。switch文でc#tupleの値の型を使用する方法

using System; 
namespace ValueTupleTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      (char letterA, char letterB) _test = ('A','B'); 
      Console.WriteLine($"Letter A: '{_test.letterA}', Letter B: '{_test.letterB}'"); 

      switch (_test) 
      { 
       case ('A', 'B'): 
        Console.WriteLine("Case ok."); 
        break; 
      } 

     } 
    } 
} 

これは残念なことにコンパイルされません。

どのようにタプルをとって、switch文の中のcaseを正しく作るのですか?

+0

タプルをスイッチ値として使用することはできません。スイッチは定数値のみを受け入れます。 – Gusman

+0

@Gusmanだけでなく、実際に。 –

+0

@YeldarKurmangaliyev新しいsintaxが型を使用することを意味するならば、型も定数と考えることができます。 – Gusman

答えて

1

返信いただきありがとうございます。

私はswitch文の使用を中止し、古いif/else文を使うことに決めました。

using System; 

namespace ValueTupleTest 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      (char letterA, char letterB) _test = ('A','B'); 
      Console.WriteLine($"Letter A: '{_test.letterA}', Letter B: '{_test.letterB}'"); 

      if (_test.letterA == 'A' && _test.letterB == 'B') 
      { 
       Console.WriteLine("Case A ok."); 
      } 
      else if (_test.letterA == 'D' && _test.letterB == '\0') 
      { 
       Console.WriteLine("Case D ok."); 
      } 

     } 
    } 
} 

私はタプルで、私が必要とするために、すべての値をテストしたい場合は、私が決めることができますこの方法。私の思うようなパフォーマンスではあまり違いはありません。

switch文でタプルを使用する別の方法がある場合は、例を挙げてください。

+1

' _test.Equals(( '' A '、' B ')) ' –

+0

を使ってタプルをあきらめる必要はありません。あなたがパーサー用のステートマシンを実装しようとしているようですね?あなたはタプルではなく、これに対してパターンマッチングを使用することができます –

4

技術的にあなたの質問に答える、あなたはタプルの値をチェックするwhenを使用することができます。

(char letterA, char letterB) _test = ('A', 'B'); 
Console.WriteLine($"Letter A: '{_test.letterA}', Letter B: '{_test.letterB}'"); 

switch (_test) 
{ 
    case var tuple when tuple.letterA == 'A' && tuple.letterB == 'B': 
     Console.WriteLine("Case ok."); 
     break; 
    case var tuple when tuple.letterA == 'D' && tuple.letterB == '\0': 
     Console.WriteLine("Case ok."); 
     break; 
} 

しかし、 ifバージョンを使用することを検討し、それが読みやすく、理解溶液であってもよいので。

この質問の反対側は、の単一責任です。あなたのメソッドは、ABD\0という文字は、単一責任の原則を破る意味を知っています。
OOPに関しては、この知識をメインコードから分離して別の方法にする方がよいでしょう。

private static bool IsCaseOk(char a, char b) 
{ 
    return (a == 'A' && b == 'B') || (a == 'D' && b == '\0'); // any logic here 
} 

public static void Main() 
{ 
    (char letterA, char letterB) _test = ('A', 'B'); 
    Console.WriteLine($"Letter A: '{_test.letterA}', Letter B: '{_test.letterB}'"); 

    if (IsCaseOk(_test.letterA, _test.letterB)) { 
     Console.WriteLine("Case ok."); 
    } else { 
     Console.WriteLine("Case not ok."); 
    } 
} 

これらの文字は、ドメイン内の任意の意味を持っている場合は、おそらくそれも2つのcharプロパティを持つクラスを作成し、そこにこのロジックをカプセル化するために、より良いアイデアです:そのような
何かがコード少しクリーン作ることができます。

+1

パターンマッチングはOOPの概念ではなく機能的です。値とのマッチングは完全にOKであり、SRPを壊すことはありません。 [Match Expression](https://fsharpforfunandprofit.com/posts/match-expression/)の「値にバインド」セクションを確認してください。何かがあれば、これにより責任を分けやすくなります。 'switch 'を2つの部分に分割することにより、Single Responsibilityは2つの異なるコードになりました –

3

タプルやパターンマッチングの使用に問題はありません。何かがある場合は、これらを使用すると、よりきれいなコードを記述し、ロジックを複数の方法に広げないようにできます。

C#7では、タプル値とは一致しません。まだです。 2つのタプルを==演算子で比較することはできません。あなたはは何ができるか、Equals 2は、2つの値のタプルを比較する使用です:

if (_test.Equals(('A','B')) 
{ 
    Console.WriteLine("Case A ok."); 
} 
else if (_test.Equals(('D','\0')) 
{ 
    Console.WriteLine("Case D ok."); 
} 

あなたが特定のパターンにマッチするパーサ、の状態matchineを作成しようとしているように思わ(?)。このは、すべての場合に1つのタプルを使用するのではなく、異なる状態クラスを指定するとパターンマッチングで動作します。

あなたは例えば、メソッドのない単一ISTATEインターフェイスを指定されませんし、すべての状態のクラスでそれを使用する必要があるすべて:あなたがいないことを意味する、

interface IMyState {}; 
public class StateA:IMyState{ public string PropA{get;set;} }; 
public class StateD:IMyState{ public string PropD{get;set;} }; 

... 
IMyState _test= new StateD(...); 

switch (_test) 
{ 
    case StateA a: 
     Console.WriteLine($"Case A ok. {a.PropA}"); 
     break; 
    case StateD d: 
     Console.WriteLine($"Case D ok. {d.PropD}"); 
     break; 
    default : 
     throw new InvalidOperationException("Where's my state ?"); 
} 

aは、d変数が強く型付けされていますIStateインターフェイスに何かを追加する必要があります。それだけでコンパイラを満足させることができます。

ステートタイプのクラスの代わりにstructsを使用すると、タプルと同じメリットが得られます。デコンストラクションを使用する場合は、それぞれのタイプにDeconstructメソッドを追加するか、別の静的クラスでDeconstruct拡張メソッドを使用します。

関連する問題