32

検索すると、デリゲートとアクションとは何かを示す例が確実に表示されます。代表者の例を挙げた基本的な本を読みました。

しかし、私が知りたいのは、現実の世界でのそれらの使用です。HelloWorldの例や動物のクラスはあまりにも基本的すぎるので教えないでください

例:

  1. それらの違いは何ですか
  2. デリゲートまたはアクションを使用するタイミング
  3. デリゲートまたはアクションを使用しない場合
  4. 彼らがオーバーキルになる可能性があるとき
4

5 に答える 5

34

Action ですDelegate。_ これは次のように定義されます。

public delegate void Action();

抽象メソッドを作成するのと同じように、独自のデリゲート型を作成できます。署名を記述しますが、実装は記述しません。次に、メソッドの参照を取得して、これらのデリゲートのインスタンスを作成します。

class Program
{
    public static void FooMethod()
    {
        Console.WriteLine("Called foo");
    }

    static void Main()
    {
        Action foo = FooMethod; // foo now references FooMethod()
        foo(); // outputs "Called foo"
    }
}
于 2012-07-07T16:31:04.257 に答える
22

デリゲートを定義するときは、基本的にメソッドのシグネチャ(戻り型と引数)を定義します。

アクションは、すでに定義されているデリゲートです(returnを無効にし、引数を指定しません)。

public delegate void Action()

あなたは定義に行き、それを自分で見ることができます。またはここのドキュメントで。 http://msdn.microsoft.com/en-us/library/system.action.aspx

探しているメソッドのシグニチャがサポートされているシグニチャと一致する場合、ほとんどの場合、既存のジェネリックデリゲート(アクションは1つ)を使用します。ジェネリックデリゲートを使用することの良い点は、それらがよく知られていることです。ほとんどの開発者は、アクションが無効/無効であることを知っています。私が自分のバージョンのアクションを定義する場合、誰もがその署名を調べる必要があり、私はすでに存在するものを複製しただけです。

たとえば...void/ voidメソッドの目的はミューテーションのみであるため、アクションはもう少しまれです。Funcは非常に一般的です(一般的なデリゲートでもあります)。フレームワーク全体、特にlinqでの使用例があります。たとえば、.whereを見てください。http://msdn.microsoft.com/en-us/library/bb534803.aspx。これはFuncであり、作業中のコレクションのタイプの要素をパラメーターとして受け取り、boolを返します。Funcがtrueを返すwhereステートメントのコンテキストでは、falseの場合は結果にそれを含めることを意味します。

public static IEnumerable<TSource> Where<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate
)
于 2012-07-07T16:19:57.387 に答える
11

Kenneth&SiegeはすでにコードとMSDNを指摘しているので、実際の例を入力してみます。

「移動」を定義するデリゲートについて考えてみます。

実世界での「アクション」デリゲートは、「実行」または「ウォーク」になります。移動する速度、移動するルート、移動にかかった時間を報告するかどうかは関係ありません。

非アクションデリゲートは、たとえば、実行速度を定義し、実行にかかった時間を返すことができます。

public delegate void MoveAction();
public delegate int MoveDelegate(int speed);

Siegeの例を拡張する..

class Program
{
    public static void Run()
    {
        Console.WriteLine("Running");
    }

    public static int RunAtSpeed(int speed)
    {
         // logic to run @ speed and return time
         Console.WriteLine("Running @ {0}", speed); 
         return 10;
    }

    public static int WalkAtSpeed(int speed)
    {
         // logic to walk @ speed and return time
         Console.WriteLine("Walking @ {0}", speed); 
         return 20;
    }

    static void Main()
    {
        Action foo = Run; 
        foo(); 

        MoveDelegate run = RunAtSpeed;
        int result1 = run(5);

        MoveDelegate walk = WalkAtSpeed;
        int result2 = walk(1);
    }
}
于 2012-07-07T18:20:06.133 に答える
5

アクションとは: 非常に単純に、Action、Func <>、Predicateはすべてデリゲートタイプです。

アクションが必要な理由: アクションは、多くの場合、アプリケーション開発に十分な、さまざまな数のパラメーターとさまざまなタイプの戻りタイプをカプセル化します。これらはシステム名前空間で提供されます。独自のデリゲートを自由に作成できます。

17種類のActionとFuncがあり、それぞれに0から16のパラメーター化された汎用引数があることに注意してください。

アクションには常に戻り値はありません。Funcには、単一のパラメーター化されたジェネリック戻り型があります。

IMHO、述語デリゲートは、引数を取り、ブール値を返すFuncと実際に同等であると定義する必要はありませんでした。

于 2015-03-19T04:32:19.553 に答える
5

繰り返し要求された実世界のサンプルコードは、「Console.WriteLine」ユーザーによる以前の回答ですでに提供されています。

それが提供された理由に関しては、私が理解したことから、アクションはあなた自身の新しい代表者を定義し続けることを節約する方法です。これは特定の署名タイプの事前定義されたデリゲートであるため、目的ごとに異なるデリゲートを作成する手間を省くことができます。事前定義されたアクションデリゲートを使用して、メソッドをポイントして実行するだけです。Funcデリゲートの場合も同じです。

実際の新機能ではなく、実際にはもっと便利です。手間をかけずに、コードを短く理解しやすくするのに役立ちます。

ポイントごとの質問に関しては、

  1. それらの違いは何ですか

変わりはない。アクションは事前定義されたデリゲートであり、新しいデリゲートを繰り返し定義する手間を省くことができます。

  1. デリゲートまたはアクションを使用するタイミング

通常、デリゲート(およびアクション)は、テーブル駆動機能が必要な場所で使用されます。つまり、特定の要件に対応するメソッドの辞書かもしれません。ここでアクションを使用すると、呼び出される最後のメソッドを簡単に変更して、他のメソッドを動的に指すようになります(ユーザーが選択した設定に基づいている可能性がありますか?)


class Program
{
    static void Main()
    {
     Dictionary<string, Action> dict = new Dictionary<string, Action>();
     dict["loadFile"] = new Action(LoadFile);
     dict["saveFile"] = new Action(SaveFile);

     dict["loadFile"].Invoke();
     dict["saveFile"].Invoke();
    }

    static void SaveFile()
    {
     Console.WriteLine("File saved!");
    }

    static void LoadFile()
    {
     Console.WriteLine("Loading File...");
    }
}

もう1つの一般的な使用法は、コールバックメソッドです。たとえば、BubbleSortクラスを使用して、コンパレータメソッドをクラスへのデリゲートとして渡します。このクラスは、BubbleSortクラスによって使用され、コードが他のすべてを処理しながら比較ロジックを定義できるようにします。これは、開始したスレッドからも使用でき、いくつかの中間アクションをコードに通知する必要がある場合、スレッドはデリゲートを呼び出します。

このSO投稿を参照して、上記の優れた例を確認できます。 https://stackoverflow.com/a/3794229/1336068

  1. デリゲートまたはアクションを使用しない場合

状況に応じて使用しないと考えることができる唯一の理由は、代理人が短期間に何百万回も呼び出される場合です。わずかなオーバーヘッドが伴います。これがアプリケーションの遅延を引き起こしている場合は、デリゲートを介さずに、関数への直接参照を使用してこれを解決するためのより良い方法を見つける必要があります。

  1. 彼らがオーバーキルになる可能性があるとき

あなたがそれらを実際の必要なしに無償で使用するとき。そうでなければ、ほとんどの状況で、それらは上記のシナリオを解決するためのエレガントな方法になり得ます。

また、このSOの回答を読んで、通常のメソッドとデリゲートの違いを確認し、デリゲート/ action /funchttps://stackoverflow.com/a/17380580/1336068を使用する場所をよりよく理解して ください。

于 2016-11-02T04:35:11.177 に答える