C #에서 액션 대리자의 사용


132

나는 C #의 Action Delegates와 함께 그들에 대해 더 많이 배우고 그들이 유용한 곳을 생각하기 위해 일하고있었습니다.

아무도 행동 대리인을 사용 했습니까? 그렇다면 왜 그렇습니까? 또는 유용한 예제를 줄 수 있습니까?

답변:


25

MSDN의 말 :

이 대리자는 Array.ForEach 메서드와 List.ForEach 메서드에서 배열 또는 목록의 각 요소에 대한 작업을 수행하는 데 사용됩니다.

그 외에는 값을 반환하지 않고 1-3 개의 매개 변수를 사용하는 일반 대리자로 사용할 수 있습니다.


다중 매개 변수 버전의 Action을 본 적이 없습니다. 감사.
mackenir

114

다음은 Action 대리자의 유용성을 보여주는 작은 예입니다.

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 확장 방법이 더 분명하게 사용됩니다.


나는 이것이 결정 테이블로 사용될 수 있다고 생각합니다.
Biswanath

3
니스-이것은 리팩토링 패턴 인 "다형성으로 조건부 대체"입니다. refactoring.com/catalog/replaceConditionalWithPolymorphism.html
David Robbins

16

짧은 이벤트 핸들러에 대한 조치를 사용할 수 있습니다.

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

긴 것들도 사용할 수 있습니다. btnSubmit.Click + = (발신자, e) => {MessageBox.Show ( "저장을 클릭했습니다!"); MessageBox.Show ( "정말 했어!"); };
tdgtyugdyugdrugdr

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 Question 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가 함께 연주하는 방식을 확장 할 수 있습니까? 메시지가 UpdateMethod : UpdateMethod ( "A Message")로 전달됩니까? 어떤 메소드가 "someDataObject"오브젝트를 사용합니까? 미리 감사드립니다
surfmuggle

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.