C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[6]: 冗長コードの改善について


(過去ログ 109 を表示中)

[トピック内 7 記事 (1 - 7 表示)]  << 0 >>

■64625 / inTopicNo.1)  冗長コードの改善について
  
□投稿者/ れお (1回)-(2012/12/12(Wed) 11:01:25)

分類:[.NET 全般] 

お世話になります。
コードがどうも冗長なので何とかもう少しスマートな方法が無いかお尋ねします。

やっているのは、計算式を文字列で受け取り答えを返す処理です。

例えば
"5.5 + calc_1_1(#1)/2 + calc_2_1(#2)*0.1"

のような式を受け取るとまず calc_1_1(#1) の部分を実数にします。

式に登場する calc_1_1() calc_2_1()は 計算を処理する
Keisanクラスの中のメソッドで他にも以下のような種類があります。
名前には簡単な正規表現で記述できる程度の規則があります。

 calc_1_1(double[] val)
 calc_1_2(double[] val)
 calc_1_3(double[] val)
 calc_1_4(double[] val)
 calc_2_1(double[] val)
 calc_2_2(double[] val)
 calc_2_3(double[] val)
 calc_2_4(double[] val)


今は以下の様なコードなのですが

  Match match = Regex.Match(strSiki, "calc_[1-4]_[1-4]");
 
  if(match.Success)
  {
    if (String.Equals(match.Value, "calc_1_1"))
    {
        ans = Keisan.calc_1_1(v);
    }
    else if (String.Equals(match.Value, "calc_1_2"))
    {
        ans = Keisan.calc_1_2(v);
    }
    else if (String.Equals(match.Value, "calc_1_3"))
    {
        ans = Keisan.calc_1_3v);
         ・・・・
         ・・・・
         ・・・・
         ・・・・
         ・・・・
    }

延々と else if を続けて記述していて冗長に感じています。
もっとスマートなやり方はないものでしょうか?

開発環境は Windows XP SP3 + VS2005 C# .NET 2.0 です。
.NETのバージョンを上げればこうできるみたいなアドバイスも歓迎です。
どうぞよろしくお願い致します。

引用返信 編集キー/
■64626 / inTopicNo.2)  Re[1]: 冗長コードの改善について
□投稿者/ shu (129回)-(2012/12/12(Wed) 11:28:32)
No64625 (れお さん) に返信

Dictionary<string, Func<double[], double>>
を使用して関数名をキーにして関数を取得出来るようにすると
行数的には減らせると思います。
関数の分DictionaryへのAddは必要になりますが。
後はReflectionを使って関数の検索をするというのも可能です。
引用返信 編集キー/
■64627 / inTopicNo.3)  Re[2]: 冗長コードの改善について
□投稿者/ pang2 (9回)-(2012/12/12(Wed) 11:47:54)
2次元配列で持つ。

delegate double f(double[] Validate);

f[,] list = new f[,] { { calc_1_1, calc_1_2, calc_1_3, calc_1_4 }, { calc_2_1, calc_2_2, calc_2_3, calc_2_4 } };
引用返信 編集キー/
■64628 / inTopicNo.4)  Re[3]: 冗長コードの改善について
□投稿者/ howling (141回)-(2012/12/12(Wed) 12:04:05)
No64627 (pang2 さん) に返信

ほぼ同じ考えの方がいた…。
今回の場合、呼び出すメソッドを文字列で判別しているようなのですが、
pang2さんの例の場合で、0〜7の間に値を収めたい時はどのようにしますか…?

なんとなく、以下の方法のいずれかを思いつきました。

1.まず、メソッドの名称を、基本名 + インデックス値にする。
  以下、基本名の変数名はMethodBaseNameとする。

2−A.基本名だけで切った文字列を、int.Parseで数値化する。
    int.Parse(string.SubString(MethodBaseName.Length));

2―B.string.CompareToメソッドを用いて、
    string.CompareTo("MethodBaseName0")と呼び、
    これの戻り値で計る(但し、これだとMethodBaseName9までしか使えないか?)

文字列自体は、Containsを使うなり、IndexOfを使うなりすればいける気はしたのですが、
速い方法ってどれなんでしょうね…。

引用返信 編集キー/
■64635 / inTopicNo.5)  Re[4]: 冗長コードの改善について
□投稿者/ れお (2回)-(2012/12/12(Wed) 15:48:20)
shuさん pang2 さん howling さん
みなさん回答ありがとうございます。

情けないのですが C#のスキルが低いため回答の内容をどう具体的に展開したら良いのかがわかりません
ただ、回答に登場する Reflection Delegate などのキーワードで調べるといろいろとヒントが
見つかりましたのでそちらも参考にしながら前に進めて行きたいと思います。

引用返信 編集キー/
■64638 / inTopicNo.6)  Re[5]: 冗長コードの改善について
□投稿者/ howling (145回)-(2012/12/12(Wed) 16:41:02)
No64635 (れお さん) に返信
とりあえずdelegateの書き方として…

delegate double f(double[] Validate); //doubleの配列型の引数1個を持ち、戻り値がdouble型である関数をfという型として定義している。

//この型の一例として、サンプル

double calc_1(double[] dParams)
{
double dReturn = 0.0;

//配列内の全ての値を加算する
foreach(double param in dParams)
{
dReturn += param;
}
return dReturn;
}

f hoge = calc_1; //そうすると、これができる

//これができると、これもできる
double[] test = new double[] { 0.1, 0.2, 0.3 };
hoge(test);

/////////////////////////////////////////////////

これの配列バージョンをpang2さんが書いてくれている。
なお、2次元配列としている理由は、
calc1なんちゃらと、calc2なんちゃらは別の部類の物だとして、区分けしてくれているため。

…と思われます。

いずれにしても、delegateはちょっと難しいので、色々読みあさるといいかもしれません。
C++の関数ポインタに似ていますが、使い方はこれだけじゃないので…。
引用返信 編集キー/
■64644 / inTopicNo.7)  Re[6]: 冗長コードの改善について
□投稿者/ れお (3回)-(2012/12/13(Thu) 09:08:27)
No64638 (howling さん) に返信

>とりあえずdelegateの書き方として…
delegateのサンプルコードありがとうございます。
とても参考になります。

>C++の関数ポインタに似ていますが、使い方はこれだけじゃないので…。
そうなんですね、実際 調べるといろんな方法があることがわかってきました。
繰り返し処理する部分なので処理速度も計りながら最適なコードを書けるよう
頑張りたいと思います。

ありがとうございます。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -