21

匿名デリゲート (入力パラメーターなし、戻り値なし) であるパラメーターを関数に渡そうとしています。

このようなもの:

private function DoSomething(delegate cmd)
{
     cmd();
}

次に、この関数を使用して、この方法で関数を呼び出したいと思います。

DoSomething(delegate
{
     Console.WriteLine("Hooah!");
});

使いやすい文体なので、この具体的な方法が欲しいです。

可能?

4

4 に答える 4

37

まさにそのような目的のために、Microsoft は.NET フレームワークでActionおよびFuncラッパー クラスを作成しました。どちらのクラスも無名関数に依存しています。匿名関数を実行するためだけに、結果を返す必要がない場合は Action を使用します。

private void DoSomething(Action action)
{
    action();
}

次のように使用できます。

DoSomething(() => 
{
    Console.WriteLine("test");
});

この() =>用語はラムダ式で、 のようなものを意味しますinput with no parameters is calling ...。詳細な説明については、ドキュメントを参照してください。

結果を返したい場合は、 Func デリゲートを使用します。

private T DoSomething<T>(Func<T> actionWithResult)
{
    return actionWithResult();
}

使用法:

Console.WriteLine(DoSomething<int>(() => 
{
    return 100;
}));

両方のラッパーには、最大 8 つのパラメーターを受け入れるオーバーライドがあります。

Func を使用する場合、最後のパラメーターは常に戻り値の型です。

// returns a string
Func<string> t = () => { return "test string"; };
// first parameter is of type int, result of type string
Func<int, string> toString = (id) => { return id.ToString(); };
// parameters are of type int and float, result is string
Func<int, float, string> sumToString = (n1, n2) => { return (n1 + n2).ToString(); };

Func ラッパーは、型付きパラメーターで直接使用できます。

Func<string, string> up = text => text.ToUpper();
Console.WriteLine(up("test"));

私はよく Func を使用して、try/catch ブロックにラップされ、何かが発生した場合にログを記録する汎用エグゼキューターを作成します。このようにして、繰り返しコードを減らします。

private T safeCallWithLog<T>(Func<T> action)
{
    try
    {           
        return action();
    }
    catch (Exception ex)
    {
        Console.WriteLine(String.Format("Oops ...: {0}", ex.Message));
    }
    // return default type if an error occured
    return default(T);
}

使用法:

var result = safeCallWithLog<DbEntry>(() =>
            {
                return databaseContext.GetEntryWithId(42);
            });

var id = safeCallWithLog<int>(() =>
                    {
                        return databaseContext.GetIdFor("J.D.");
                    }); 

元のデリゲートの概念を引き続き使用できます。Action クラスと Func クラスは、定義済みのジェネリック デリゲート メソッドの単なるラッパーです。

// declare delegate contract
private delegate void output();
// create caller method
private void method(output fun)
{
    fun();
}
// some test functions, that must match exactly the delegate description
// return type and number of arguments
private void test1()
{
    Console.WriteLine("1");
}

private void test2()
{
    Console.WriteLine(DateTime.Now.ToString());
}

// call different methods
method(test1);
method(test2);
// inline call without hard coded method
method(delegate() 
{
    Console.WriteLine("inline");
});
于 2014-02-15T09:41:53.083 に答える
3

.NET には、これらが組み込まれています。Actionは、パラメーターや戻り値の型がない場合に必要なものです。

private function DoSomething(Action cmd)
{
    cmd();
}

Action<int, int>パラメーターを持ち、戻り値の型を持たないデリゲートが必要な場合 (たとえば、2 つの int を取り、戻り値を持たないメソッドの場合) には、一般的なバージョンの Action もあります。

FuncそしてPredicate(それらのジェネリックバージョンも)存在します。

于 2014-02-15T09:41:59.183 に答える
0

確かにそれは可能です。戻り値の型のないメソッドの場合は、それ以外を使用しActionますFunc<>

public void Function(Action action)
{
    action();
}

そしてそれを次のように呼び出します

Function(() => System.Console.WriteLine("test"));

キーワードの代わりにラムダを使用するとさらに快適delegateです。を使用してアクションを実行することもできますaction.Invoke()が、私の意見では、実際にはメソッドのように呼び出す方がよいでしょう。

于 2014-02-15T09:42:00.840 に答える