web-dev-qa-db-ja.com

コードを変数に割り当てる

変数を作成して、次のようなコード行を割り当てることは可能ですか?

ButtonClicked = (MessageBox.Show("Hello, World!"));

...したがって、変数を使用すると、コード行が実行されます。

124
user3539891

次のように Action に割り当てることができます。

var ButtonClicked = new Action(() => MessageBox.Show("hi"));

次に呼び出します:

ButtonClicked();

完全を期すために(さまざまなコメントに関して)...

エリックが述べたように、複数行のコードを実行できます。

var ButtonClicked = new Action(() =>
{
    MessageBox.Show("hi");

    MessageBox.Show("something else");  // something more useful than another popup ;)
});

Timが述べたように、Actionキーワードは省略できます

Action ButtonClicked = () => MessageBox.Show("hi");

Action ButtonClicked = () =>
{
    // multiple lines of code
};

空の括弧に関するKRyanのコメントに対処するために、アクションに送信できるようにするパラメーターのリストを表します(この場合、なし)

たとえば、表示するメッセージを指定する場合は、パラメータとして「メッセージ」を追加できます(注意してください私は変更しましたActiontoAction<string>単一の文字列パラメータを指定するには)

Action<string> ButtonClicked = (message) => MessageBox.Show(message);

ButtonClicked("hello world!");
89
Grant

あなたの場合、delegateを使用します。

デリゲートがどのように機能し、その概念を理解することで簡単なフォームに到達する方法を見てみましょう

_// Create a normal function
void OnButtonClick()
{
    MessageBox.Show("Hello World!");
}
// Now we create a delegate called ButtonClick
delegate void ButtonClick();
_

おわかりのように、デリゲートは通常の関数の形式をとりますが、引数はありません(他のメソッドと同じように、任意の量の引数を取ることができますが、簡単にするため、引数は取りません)。

次に、持っているものを使用しましょう。他の変数を定義するのと同じようにデリゲートを定義します。

_ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
_

基本的にButtonClickedという名前の新しい変数を作成しました。これはButtonClick(デリゲート)のタイプを持ち、使用するとOnButtonClick()メソッドでメソッドを実行します。
それを使用するには、単にButtonClicked();を呼び出します。

したがって、コード全体は次のようになります。

_delegate void ButtonClick();

void OnButtonClick()
{
    MessageBox.Show("Hello World!");
}

void Foo()
{
    ButtonClick ButtonClicked = new ButtonClick(OnButtonClick);
    ButtonClicked(); // Execute the function.
}  
_

ここから、ラムダ式に移動して、あなたの状況でラムダ式がどのように役立つかを確認できます。
public delegate void Action();として定義されます
毎回新しいデリゲートを定義する代わりに、いつでもニーズに合わせて使用​​できます。たとえば、前のコンテキストでは、次のように書くことができました

_Action ButtonClicked = new Action(OnButtonClick);
ButtonClicked();
_

同じことをしたでしょう。
これで、デリゲートのさまざまな使用方法を見てきました。最初のラムダ式を使用しましょう。ラムダ式は匿名関数です。したがって、これらは通常の機能ですが、名前はありません。それらは次の形式です。

_x => DoSomethingWithX(x);
(x) => DoSomethingWithX(x);
(x,y) => DoSometingWithXY(x,y);
() => Console.WriteLine("I do not have parameters!");
_

この場合、パラメーターはないため、最後の式を使用します。これをOnButtonClick関数として使用できますが、名前付き関数がないという利点があります。代わりに次のようなことができます。

_Action ButtonClicked = new Action( () => MessageBox.Show("Hello World!") );
_

またはさらに簡単に、

_Action ButtonClicked = () => MessageBox.Show("Hello World!");
_

それから、単にButtonClicked();を呼び出しますただし、次のようになります。

_Action ButtonClicked = () => 
{
    MessageBox.Show("Hello World!");
};
ButtonClicked();
_

たとえば、次のような関数を実行することもできます。

_new Action(() => MessageBox.Show("Hello World!"))();
_

長い投稿で申し訳ありませんが、あまりにも混乱しないことを願っています:)

編集:私は頻繁に使用されていませんが、ラムダ式を理解しやすくすることができる代替形式であることを忘れていました:

_new Action(delegate() {
    Console.WriteLine("I am parameterless");
})();
_

また、ジェネリックの使用:

_// Defines a delegate that has one parameter of type string. You could pass as many parameters as you want.
new Action<string>(delegate(string x) {
    Console.WriteLine(x);
})("I am a string parameter!");
_

ラムダ式を使用することもできますが、パラメーターの型を定義する必要はありません(ただし、場合によっては可能性があります)。たとえば、上記のコードは単純に次のように記述できます。

_new Action<string>(x => {
    Console.WriteLine(x);
})("I am a string parameter!");
_

または:

_new Action<string>(x => Console.WriteLine(x))("I am a string parameter!");
_

EDIT2:
_Action<string>_はpublic void delegate Action(string obj);の表現です
_Action<string,string>_はpublic void delegate Action(string obj, string obj2);の表現です
一般に、_Action<T>_はpublic void delegate Action<T>(T obj);の表現です

EDIT3:私はこの投稿がしばらくここにあることを知っていますが、これは言及しないのは本当にクールだと思います:あなたはこれを行うことができます。これはあなたの質問にほとんど関連しています:

_dynamic aFunction = (Func<string, DialogResult>)MessageBox.Show;
aFunction("Hello, world!");
_

または単に:

_Func<string, DialogResult> aFunction = MessageBox.Show;
aFunction("Hello, world!");
_
51
user3439065

Lazy クラスは、要求するまで計算されない値を表すように特別に設計されています。構築方法を定義するメソッドを提供して構築しますが、そのメソッドの実行は(値を要求する複数のスレッドに直面しても)1回しか処理せず、追加の要求に対して既に構築された値を返すだけです:

var foo = new Lazy<DialogResult>(()=>MessageBox.Show("Hello, World!"));

var result = foo.Value;
7
Servy

あなたの質問を読んでいる方法は、これはGUIコントロールのコンテキストにありますか?

これがWPFにある場合、コントロールからのコマンドを処理する「正しい」方法を見てください: http://msdn.Microsoft.com/en-us/library/ms752308(v = vs.110)。 aspx

...しかし、それは苦痛とやり過ぎになる可能性があります。より単純な一般的なケースでは、次のようなイベントハンドラを探しているかもしれません。

myButton.Click += (o, e) => MessageBox.Show("Hello, World!");

そのイベントハンドラーはさまざまな方法で処理できます。上記の例では匿名関数を使用していますが、次のこともできます。

Action<object, RoutedEventArgs> sayHello = (o, e) => MessageBox.Show("Hello, World");
myButton.Click += new RoutedEventHandler(sayHello);

...ちょうどあなたが求めていたように、変数として割り当てられた関数(または、ここではvoidを返すため、「アクション」)で。

4
Zaccone

C#コードを変数に割り当て、実行時にコンパイルしてコードを実行できます。

  • コードを書く:

    // Assign C# code to the code variable.
    string code = @"
    using System;
    
    namespace First
    {
        public class Program
        {
            public static void Main()
            {
                " +
                "Console.WriteLine(\"Hello, world!\");"
                + @"
            }
        }
    }
    ";
    
  • コンパイラーのプロバイダーとパラメーターを作成します。

    CSharpCodeProvider provider = new CSharpCodeProvider();
    CompilerParameters parameters = new CompilerParameters();
    
  • コンパイラーのパラメーターを定義します。

    // Reference to System.Drawing library
    parameters.ReferencedAssemblies.Add("System.Drawing.dll");
    // True - memory generation, false - external file generation
    parameters.GenerateInMemory = true;
    // True - exe file generation, false - dll file generation
    parameters.GenerateExecutable = true;
    
  • アセンブリのコンパイル:

    CompilerResults results = provider.CompileAssemblyFromSource(parameters, code);
    
  • エラーを確認します。

    if (results.Errors.HasErrors)
    {
            StringBuilder sb = new StringBuilder();
    
            foreach (CompilerError error in results.Errors)
            {
                    sb.AppendLine(String.Format("Error ({0}): {1}", error.ErrorNumber, error.ErrorText));
            }
    
            throw new InvalidOperationException(sb.ToString());
    }
    
  • アセンブリ、タイプ、およびメインメソッドを取得します。

    Assembly assembly = results.CompiledAssembly;
    Type program = Assembly.GetType("First.Program");
    MethodInfo main = program.GetMethod("Main");
    
  • それを実行します:

    main.Invoke(null, null);
    

参照:

http://www.codeproject.com/Tips/715891/Compiling-Csharp-Code-at-Runtime

1
Amir Saniyan