none
if分の条件式を文字列で渡せるようなことしたい RRS feed

  • 質問

  • そもそもこのようなことはできるのでしょうか。

    if分の条件式を文字列で渡して評価をしたい。

    具体的に使用するシーンとして、例えば式自体はプログラム中に、

    その引き渡す文字列は外部のテキストファイルから取得するようなことを想定しています。

    (例)

    if ( a==1 ) {b =1;}

    この a== 1のところを、

    if ( s ) {b =1;} として、

    sには、a==1 だったり、b==1 のようなのを引き渡したいです。

    2018年5月12日 11:18

回答

  • 簡潔に書くと、冒頭の質問で示された例や、途中の投稿で示されたテストプログラムの例では「無理」です。
    (ローカル変数の名前は実行時には残っていないため。かんたんではない…ではなく、できない)

    あくまで、「ローカル変数を対象に外部ファイルに自由に書ける」という仕様が無理というだけです。
    たとえば、「外部ファイルから生成した動的メソッド」に引数として a や b を渡しても良いなら、十分対応できる範囲でしょう。
    (外部ファイルで使いたい変数をすべて引数で渡す)

    // 外部ファイルをコンパイルして Func<>にするメソッドのイメージ
    Func<int, int, bool> func = CompileFromAnotherFile(); 
    // 外部処理にローカル変数a,bを自由にさせることは無理なので、引数として渡してあげる
    if (func(a, b)) { Console.WriteLine("true"); }
    2018年5月12日 13:27
    モデレータ
  • 質問に率直に回答するのであれば、Scripting APIというのがあるので、これを組み込むことになるでしょうか。スクリプトから参照したい変数もグローバル変数として渡してやればアクセスできます。

    ただし、この仕組みは大掛かりでコンパイラーを丸ごと抱え込み実行時にコンパイルしているようなものなので、質問文のノリの軽さとは釣り合わないようにも感じられます。

    なお開発時に判定式を試行錯誤する程度であれば、このような仕組みを導入するのではなく都度コンパイルすることをお勧めします。

    2018年5月12日 21:22

すべての返信

  • s を bool 型にして、それに a == 1 とか b == 1 を代入してみてください。
    2018年5月12日 11:25
  • http://www.atmarkit.co.jp/fdotnet/dotnettips/100compile/compile.html
    こんな感じで外に「ソースコード」として生成して、実行時にコンパイルして、ロード、実行、アンロード、かなぁ?

    「x」がクラスのメンバーなら、リフレクションという方法もあるかも。
    http://ufcpp.net/study/csharp/dyn_usage.html#code-generation
    https://qiita.com/kiichi54321/items/0a2eed8268eea2a36da0


    Jitta@わんくま同盟

    2018年5月12日 12:26
  • 回答ありがとうございます。

    >s を bool 型にして、それに a == 1 とか b == 1 を代入してみてください。

    プログラム内で書く分には大丈夫ですが、その式自体を文字列として外部ファイルから取得する必要が

    あるため、文字列で処理しなければなりません。そのためbool 型のsへいれるには、

    キャストのようなものをするイメージですが、これがCS0029が出て出来ません。

    ーーーーーーーーテストプログラム(エラーCS0029)

        bool b = false;
        string s = null;

         int a = 1;

         b = "a==1";     //a==1は本来テキストファイルから読み込むとする

          if (b)
          {
                 Console.WriteLine("true");
          }
          else
          {
                Console.WriteLine("false");

          }

    ーーーーーーーーテストプログラム(エラーCS0030)

             bool b = false;
                string s = null;

                int a = 1;

                b = (bool)"a==1";     //a==1は本来テキストファイルから読み込むとする

                if (b)
                {
                    Console.WriteLine("true");
                }
                else
                {
                    Console.WriteLine("false");

                }

            }

    2018年5月12日 12:39
  • その a == 1 の「a」や「1」といった要素はどういった範囲まで対応するつもりですか?

    たとえば、ローカル変数である「a」の名前はコンパイルした DLL になった時点で失われます。
    実行時に外部から指定された文字列に基づいて、ローカル変数を選び取って比較するみたいなことはできません。

    そういったことをしたいのなら、コンパイル時点で「a」という変数を「a」という文字列と紐付けるみたいな作り込みが必要になるので、「外部ファイルで自由に書ける」と言うことは無理があります。

    ただし、プロパティ、メソッド、フィールド変数など、リフレクションで取得可能な範囲であれば、実現の可能性はあると思います。

    さて、繰り返しになりますが、どこまでやりたいのでしょうか?

    2018年5月12日 12:44
    モデレータ
  • 回答ありがとうございます。

    リフレクションや式木は調べてみましたが、もっと簡単にかける方法はないかな?

    と思って本質問を立てました。

    頂いたURL参考にさせて頂きます。Orz

    2018年5月12日 13:01
  • >実行時に外部から指定された文字列に基づいて、ローカル変数を選び取って比較するみたいなことはできません。そういったこと>をしたいのなら、コンパイル時点で「a」という変数を「a」という文字列と紐付けるみたいな作り込みが必要になるので、「外>部ファイルで自由に書ける」と言うことは無理があります。

    回答ありがとうございます。

    私には頂いた回答が難しくてなんと回答してよいかわかりませんが、簡単にできないことはわかりました。

    2018年5月12日 13:04
  • 簡潔に書くと、冒頭の質問で示された例や、途中の投稿で示されたテストプログラムの例では「無理」です。
    (ローカル変数の名前は実行時には残っていないため。かんたんではない…ではなく、できない)

    あくまで、「ローカル変数を対象に外部ファイルに自由に書ける」という仕様が無理というだけです。
    たとえば、「外部ファイルから生成した動的メソッド」に引数として a や b を渡しても良いなら、十分対応できる範囲でしょう。
    (外部ファイルで使いたい変数をすべて引数で渡す)

    // 外部ファイルをコンパイルして Func<>にするメソッドのイメージ
    Func<int, int, bool> func = CompileFromAnotherFile(); 
    // 外部処理にローカル変数a,bを自由にさせることは無理なので、引数として渡してあげる
    if (func(a, b)) { Console.WriteLine("true"); }
    2018年5月12日 13:27
    モデレータ
  • >たとえば、「外部ファイルから生成した動的メソッド」に引数として a や b を渡しても良いなら、十分対応できる範囲でしょ>>う。(外部ファイルで使いたい変数をすべて引数で渡す)

    回答ありがとうございます。

    ローカル変数で記載したのは例題のため、実際のシステムではローカル変数にこだわらないです。

    2018年5月12日 13:55
  • サンプルソースありがとうございます。

    参考にさせて頂きます。

    2018年5月12日 14:06
  • > プログラム内で書く分には大丈夫ですが、その式自体を文字列として外部ファイルから取得する必要があるため、

    失礼ながら、見当違いの方向に進んでいるように思います。(全くの知識不足のような気がします)

    全体的なシナリオ・ストーリーを含めてやりたいことを書いていただけると、質問に書いてあることはできない or 不適切だけど、やりたいことはこうすればできるというような代案が出てくるかもしれません。

    2018年5月12日 14:32
  • 回答ありがとうございます。

    やりたいシステムですが、下記を想定しています。

    (例)

    ・とあるプログラム(以下、A.exe)は、テキストファイル(以下、B.txt)を読み込む

    ・B.txtはif分の条件式(条件部分のみ)を毎行羅列している

      ( a == 1)  //①

      ( b ==1 )  //②

      ・・・

    ・A.exeはB.txtをリードし、ループ処理にて取得したB.txtの各行を評価する

    このときに①や②はstring型で取得しているので、ifでbool型の処理ができなくて困ってました。

     if (※) { } //イメージは左記のように※はループ処理で①②・・・と評価していく

    2018年5月12日 15:12
  • WebSurferさんのは、そういう仕様に至る背景は?ってことですよ。
    私も、センサーからの情報で何をどうすればいいのか決まっていないからコードを書ける様に、ただしプログラムのことはわからないから判定式だけでいい様にして、と言われたことがあります。結局、要望を整理して行くとコードとか判定式を外から供給するとかということは不要だとわかったので、それなりの対応をしました。

    Jitta@わんくま同盟

    2018年5月12日 21:08
  • 質問に率直に回答するのであれば、Scripting APIというのがあるので、これを組み込むことになるでしょうか。スクリプトから参照したい変数もグローバル変数として渡してやればアクセスできます。

    ただし、この仕組みは大掛かりでコンパイラーを丸ごと抱え込み実行時にコンパイルしているようなものなので、質問文のノリの軽さとは釣り合わないようにも感じられます。

    なお開発時に判定式を試行錯誤する程度であれば、このような仕組みを導入するのではなく都度コンパイルすることをお勧めします。

    2018年5月12日 21:22
  • 話が噛み合ってないように思います。

    > やりたいシステムですが、下記を想定しています。

    ・・・中略・・・

    >  if (※) { } //イメージは左記のように※はループ処理で①②・・・と評価していく

    上記の局所的な手段の前に、全体的なあなたのやりたいことのシナリオ・ストーリーがあるはずですよね? それは何かを聞いています。

    上記の局所的な手段は、全体的なやりたいことを達成するための一部としてあなたが考えたことでしょうけど、そんなことはできないので、別の手段を考えた方が良いということです。

    別の手段を考えるために、先の私のレスで「全体的なシナリオ・ストーリーを含めてやりたいことを書いていただけると・・・」と書きました。

    それを書いてもらえると「全体的なシナリオ・ストーリーはこうすれば実現できる」というような代案も出てくるかもしれません。

    今提供されている情報だけではそういう代案の提案は少なくとも自分はできないです。

    想像をベースに何か言えるかもしれませんが、想像が間違っていると混乱を招くのみで、逆に解決から遠のくかもしれませんので。

    2018年5月13日 1:29
  • 遅くなりました。

    回答ありがとうございます。

    率直な回答を頂く方が大変助かります。

    参考にさせて頂きます。

    2018年5月13日 11:38
  • >上記の局所的な手段は、全体的なやりたいことを達成するための一部としてあなたが考えたことでしょうけど、そんなことはできないので、別の手段を考えた方が良いということです。

    回答ありがとうございます。

    おっしゃるとおり別の手段を検討します。

    2018年5月13日 11:45