質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.50%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

5回答

1988閲覧

case文の場合分けが多過ぎる問題

tools.i

総合スコア11

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

0グッド

0クリップ

投稿2018/05/10 01:33

命令文が1行ごとに連なったテキストファイル(下記のPlain text)を読み込んで、
その行の命令を実行するプログラム(下記C#)を作成しています。

下記のようなプログラムだと、命令の種類が多数あるため、case文が長くなる上、対応する関数を同じファイルに書き込んでいるので、そのプログラムファイルが無関係な命令文が入り混じった冗長なものになっています。

すっきり書くような常套手段のようなものはありますか?

なお、私はC言語とc++は数年前ですが、そこそこ経験がありますが、c#でのプログラミングはこれが初めてです。

よろしくお願いします。

text

1Set_X_Parameter, 1, 2, 0.005 2Set_Y_Thickness, 10, 2.5 3....

C#

1switch (cmd) 2{ 3case "Set_X_Parameter": 4 Set_X_Parameter(cmd_args); 5 break; 6case "Set_Y_Thickness": 7 Set_Y_Thickness(cmd_args); 8 break; 9// 10// 11// たくさん続く 12// 13// 14default: 15 break; 16}

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

sazi

2018/05/10 01:51

その固定値の内容が条件により収斂されるもので無い限り、固定値の分岐が有るという情報だけでは、分岐を減らすことなどできないと思います。 固定値の分岐によって何を行っているかの情報があれば、別でしょうけど。
sazi

2018/05/10 02:34

固定値と呼び出す関数名が一致しているのですね。失礼しました。
tools.i

2018/05/10 05:11

正直、さっぱり分かりません。
guest

回答5

0

メソッド名がわかるならリフレクションが使えます。
typeof演算子やGetTypeメソッドでTypeを取得し、GetMethodメソッドでMethodInfoを取得すれば、Invokeメソッドで呼び出すことができます。

ただし、パフォーマンスは良くないので注意してください。

投稿2018/05/10 02:16

YamakawaJunichi

総合スコア630

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2018/05/10 02:41

呼び出す度に MethodInfo を取得するならパフォーマンスは良くありませんが、キャッシュしておけば良いだけなので、私もこの方法を取ると思います。 そうでなければ DynamicObject で動的オブジェクトを作るかもしれません。
guest

0

他の回答者さん達の回答をまとめてコードにしました。

各関数は private static void **(string[]) で統一されていることが前提です。

csharp

1static Dictionary<string, Action<string[]>> cache; 2 3static void Init() 4{ 5 cache = typeof(クラス名) 6 .GetMethods(BindingFlags.Static | BindingFlags.NonPublic) 7 .Where(mi => mi.ReturnType == typeof(Void)) 8 .Where(mi => mi.GetParameters().SingleOrDefault()?.ParameterType == typeof(string[])) 9 .ToDictionary( 10 mi => mi.Name, 11 mi => mi.CreateDelegate(typeof(Action<string[]>), null) as Action<string[]>); 12} 13 14public static void InvokeCommand(string name, string[] args) 15{ 16 if (cache.TryGetValue(name, out var cmd)) 17 { 18 cmd(args); 19 } 20}

何やってるかわからないと思うので、解説を追記します。

.NET にはリフレクションという機能があり、プログラム実行時にプロパティやメソッドを検索できます。

上のコードではリフレクションを使い、
まず static かつ public では無いメソッドを片っ端から取得します。
さらに、戻り値無し、引数が一つでその型が string[] という情報を元にコマンドだけを絞り込んでいきます。

また、この処理中に何度か配列が返ってくるのですが、これをスマートに処理する Linq という機能を使っています。
Where, SingleOrDefault, ToDictionary が Linq です。

=> の部分はラムダ式といって、デリゲート(後述)を簡単に定義する記法です。

リフレクションは負荷のかかる処理なので、デリゲート(関数ポインタのようなもの)に変換して負荷を軽くします。
これによって、各コマンドのデリゲート(関数ポインタ)が作成されます。
こんな感じです。
delegate void Action<string[]>(string[]);

switch文の処理はまるまる Dictionary.TryGetValue() で置き換えました。

難しいとは思いますが、 C# のエッセンスが詰まっているのでぜひ勉強してみてください。

投稿2018/05/10 03:59

編集2018/05/11 05:21
gaya-K

総合スコア449

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tools.i

2018/05/11 00:47

勉強します。どうもありがとうございました。
guest

0

ちょっとすっきりするかも?

C#

1public void CommandInvoke(string cmd, string[] cmd_args) 2{ 3 Dictionary<string, Action<string[]>> commandDic = new Dictionary<string, Action<string[]>>(); 4 commandDic.Add("Set_X_Parameter", a => Set_X_Parameter(a)); 5 commandDic.Add("Set_Y_Thickness", a => Set_Y_Thickness(a)); 6 7 commandDic[cmd].Invoke(cmd_args); 8}

投稿2018/05/10 02:41

hihijiji

総合スコア4150

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

よくやるのは、コマンド実行のルーチンを複数に分ける仕組みを作ってやりますね
ある程度コマンド群をグループに分けて、

C#

1 2bool commandA(string cmd) 3{ 4 switch(cmd){ 5 case "uniuni": 6 うにうに 7 break; 8 ... 9 ... 10 default: 11 return false; 12 } 13 return true; 14} 15 16bool commandB(string cmd){ ... } 17bool commandC(string cmd){ ... } 18bool commandD(string cmd){ ... } 19 20 21// メインのコマンド実行ルーチン 22void commandMain(string cmd) 23{ 24 if(commandA(cmd)) return; 25 if(commandB(cmd)) return; 26 if(commandC(cmd)) return; 27 if(commandD(cmd)) return; 28} 29

これでグループごとにファイル変えたり、クラスを変えたりできるし、デバッグもしやすくなります

投稿2018/05/10 02:33

編集2018/05/10 02:56
y_waiwai

総合スコア87719

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tools.i

2018/05/11 00:46

勉強します。
tools.i

2018/05/11 00:48

とりあえず、すぐ理解できたので、僭越ながらベストアンサーということで。
guest

0

デザイン時テンプレートとしてT4テキストテンプレートを使い、
コードを自動生成するという方法があります。

投稿2018/05/10 03:38

ozwk

総合スコア13512

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.50%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問