C#でのアクションデリゲートの使用[終了]


132

私はアクションデリゲートをC#で操作し、それらについてさらに学び、それらがどこに役立つかを考えていました。

誰かがアクションデリゲートを使用しましたか?それとも役に立つかもしれない例をいくつか挙げていただけますか?

回答:


25

MSDNは言う:

このデリゲートは、Array.ForEachメソッドおよびList.ForEachメソッドによって、配列またはリストの各要素に対してアクションを実行するために使用されます。

それ以外は、値を返さずに1〜3個のパラメーターを受け取る汎用デリゲートとして使用できます。


Actionのマルチパラメーターバージョンに気づきませんでした。ありがとう。
マッケニル2008

114

アクションデリゲートの有用性を示す小さな例を次に示します

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        Action<String> print = new Action<String>(Program.Print);

        List<String> names = new List<String> { "andrew", "nicole" };

        names.ForEach(print);

        Console.Read();
    }

    static void Print(String s)
    {
        Console.WriteLine(s);
    }
}

foreachメソッドは名前のコレクションを反復処理し、コレクションのprint各メンバーに対してメソッドを実行することに注意してください。これは、より機能的なプログラミングスタイルに移行するC#開発者にとって、少しパラダイムシフトです。(その背後にあるコンピュータサイエンスの詳細については、http//en.wikipedia.org/wiki/Map_(higher-order_function)を参照してください)

C#3を使用している場合は、次のようなラムダ式を使用してこれを少しスリックできます。

using System;
using System.Collections.Generic;

class Program
{
    static void Main()
    {
        List<String> names = new List<String> { "andrew", "nicole" };

        names.ForEach(s => Console.WriteLine(s));

        Console.Read();
    }
}

68

ええと、あなたができることの一つは、スイッチがある場合です:

switch(SomeEnum)
{
  case SomeEnum.One:
      DoThings(someUser);
      break;
  case SomeEnum.Two:
      DoSomethingElse(someUser);
      break;
}

そして、アクションの強力な力で、そのスイッチを辞書に変えることができます:

Dictionary<SomeEnum, Action<User>> methodList = 
    new Dictionary<SomeEnum, Action<User>>()

methodList.Add(SomeEnum.One, DoSomething);
methodList.Add(SomeEnum.Two, DoSomethingElse); 

...

methodList[SomeEnum](someUser);

または、これをさらに進めることができます。

SomeOtherMethod(Action<User> someMethodToUse, User someUser)
{
    someMethodToUse(someUser);
}  

....

var neededMethod = methodList[SomeEnum];
SomeOtherMethod(neededMethod, someUser);

ほんの数例。もちろん、より明白な使用法はLinq拡張メソッドです。


これは決定表として使用できると思います。
ビスワナート

3
いいですね-これは、「条件付きを多態性に置き換える」リファクタリングパターンです。 refactoring.com/catalog/replaceConditionalWithPolymorphism.html
デヴィッド・ロビンス

16

短いイベントハンドラのアクションを使用できます。

btnSubmit.Click += (sender, e) => MessageBox.Show("You clicked save!");

長いものにも使用できます。btnSubmit.Click + =(sender、e)=> {MessageBox.Show( "You clicked save!"); MessageBox.Show( "あなたは本当にやった!"); };
tdgtyugdyugdrugdr 2015

15

このようなアクションデリゲートをプロジェクトで一度使用しました。

private static Dictionary<Type, Action<Control>> controldefaults = new Dictionary<Type, Action<Control>>() { 
            {typeof(TextBox), c => ((TextBox)c).Clear()},
            {typeof(CheckBox), c => ((CheckBox)c).Checked = false},
            {typeof(ListBox), c => ((ListBox)c).Items.Clear()},
            {typeof(RadioButton), c => ((RadioButton)c).Checked = false},
            {typeof(GroupBox), c => ((GroupBox)c).Controls.ClearControls()},
            {typeof(Panel), c => ((Panel)c).Controls.ClearControls()}
    };

これは、フォーム上のすべてのコントロールをクリアしてデフォルトに戻すことができるように、コントロールのタイプに対するアクション(メソッド呼び出し)を格納するだけです。


ニース、大きな変更ではありませんが、keyedbyTypeCollectionと呼ばれるものがありますが、dictioinary(type、Object)をラップすると思いますが、そうかもしれません。
Biswanath

13

Action <>の使用例を示します。

Console.WriteLineには、を満足させる署名がありますAction<string>

    static void Main(string[] args)
    {
        string[] words = "This is as easy as it looks".Split(' ');

        // Passing WriteLine as the action
        Array.ForEach(words, Console.WriteLine);         
    }

お役に立てれば


11

不正なクロススレッドコールを処理するときに使用します。次に例を示します。

DataRow dr = GetRow();
this.Invoke(new Action(() => {
   txtFname.Text = dr["Fname"].ToString();
   txtLname.Text = dr["Lname"].ToString(); 
   txtMI.Text = dr["MI"].ToString();
   txtSSN.Text = dr["SSN"].ToString();
   txtSSN.ButtonsRight["OpenDialog"].Visible = true;
   txtSSN.ButtonsRight["ListSSN"].Visible = true;
   txtSSN.Focus();
}));

私はReed Copsey SOのユーザー65358にソリューションの功績を認めなければなりません。回答付きの私の完全な質問はSO質問2587930です


3

イベントハンドラーのコールバックとして使用しました。イベントを発生させるとき、文字列をパラメータとするメソッドを渡します。イベントの発生は次のようになります。

SpecialRequest(this,
    new BalieEventArgs 
    { 
            Message = "A Message", 
            Action = UpdateMethod, 
            Data = someDataObject 
    });

メソッド:

   public void UpdateMethod(string SpecialCode){ }

は、イベントArgsのクラス宣言です。

public class MyEventArgs : EventArgs
    {
        public string Message;
        public object Data;
        public Action<String> Action;
    }

このようにして、イベントハンドラーから渡されたメソッドをいくつかのパラメーターを指定して呼び出し、データを更新できます。これを使用して、ユーザーに情報を要求します。


こんにちはSorskoot、UpdateMethod、MyEventArgs、および新しいBalieEventArgsが一緒に再生される方法を拡張できますか。文字列MessageはUpdateMethodに渡されますか:UpdateMethod( "A Message")?オブジェクト「someDataObject」を使用するメソッドはどれですか?よろしくお願いします
お願いします surfmuggle 2013年

2

テストでは、多くのアクションデリゲート機能を使用します。デフォルトのオブジェクトを作成する必要があり、後でそれを変更する必要がある場合。私は少し例を作りました。デフォルトの人物(John Doe)オブジェクトを作成するには、BuildPerson()関数を使用します。後でJane Doeも追加しますが、彼女の誕生日と名前、身長を変更します。

public class Program
{
        public static void Main(string[] args)
        {
            var person1 = BuildPerson();

            Console.WriteLine(person1.Firstname);
            Console.WriteLine(person1.Lastname);
            Console.WriteLine(person1.BirthDate);
            Console.WriteLine(person1.Height);

            var person2 = BuildPerson(p =>
            {
                p.Firstname = "Jane";
                p.BirthDate = DateTime.Today;
                p.Height = 1.76;
            });

            Console.WriteLine(person2.Firstname);
            Console.WriteLine(person2.Lastname);
            Console.WriteLine(person2.BirthDate);
            Console.WriteLine(person2.Height);

            Console.Read();
        }

        public static Person BuildPerson(Action<Person> overrideAction = null)
        {
            var person = new Person()
            {
                Firstname = "John",
                Lastname = "Doe",
                BirthDate = new DateTime(2012, 2, 2)
            };

            if (overrideAction != null)
                overrideAction(person);

            return person;
        }
    }

    public class Person
    {
        public string Firstname { get; set; }
        public string Lastname { get; set; }
        public DateTime BirthDate { get; set; }
        public double Height { get; set; }
    }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.