2011-05-13 1 views
4

을 나타냅니다. 액션은 객체에 대해 수행 할 액션을 나타내지 만, 몇 가지 코드베이스에서는 Action<Action<T>>으로 선언 된 매개 변수를 보았으며 수행 할 액션을 이해하려고 애썼지 만 다른 행동이 의미합니다.개념적으로 무엇을 할 것인가 <Action<T>>는

그래서 개념적으로는 Action<Action<T>>이 무엇을 나타 냅니까? 하나를 사용하는 예제를 제안 할 수 있습니까?

답변

6

끝으로 시작하여 패턴을 사용하여 긴 스레드가 주 스레드에서 실행되는 동안 다중 스레드 "진행률"대화 상자를 만듭니다. 진도 막대 및 상태 텍스트를 업데이트하는 방법을 알고있는 람다 (lambda)를받는 작업을 수행하는 람다 (lambda)로 함수를 만드는 대화 상자를 호출합니다. 이런 식으로 뭔가 :

LongRunningOperation.Run((update)=> 
    { 
    update("phase 1"); 
    // do work for phase 1 

    update("phase 2"); 
    // do work for phase 2 
    }); 

그래서 내 Run 기능은 다음과 같이 선언한다 :

public static void Run(Action<Action<string>> worker); 

일반화,이 패턴을 사용 함수 자체에서 람다를 수신하는 작업자 람다.

3

Action<Action<T>>Action<T>을 인수로 사용하는 대리인입니다. 이렇게하면 호출 될 때 두 번째 대리자 (형식 : Action<T>)가 전달되는 대리인을 전달할 수 있습니다.

그러나이 용도는 매우 드물지만 (또는 있어야합니다). 일반적으로 단일 Action<T>을 사용하고이를 전달할 수 있습니다. 내가 이것을 볼 수있는 유일한 곳은 컬렉션 내부에 델리게이트 집합을 저장하는 것과 같은 시나리오 일 것입니다.

예를 들어 Person 클래스에서 작동하는 일련의 작업이 있다고 가정합니다. 이는 다음과 같이 정의 할 수 있습니다 : 당신이 어떤 특정 사람에 따라 이러한 모든 방법을 실행하기 위해 List<T>.ForEach를 사용하기를 원한다면 List<Action<Person>> actions; 어떤 기준을 당신은 같은 할 수 맞게 제공이 주어진 :

Person person = GetPersion(); 
actions.ForEach(action => 
    { 
     if (person.Foo) 
      action(person); // Call the action on the person 
    }); 

을 위의 람다 것 Action<Action<Person>>. (개인적으로 이와 같은 코드를 작성하지 않고 대신 정상적인 foreach 루프를 권장합니다.이 방법이 어떻게 발생 하는지를 보여주기위한 것입니다.)

2

다른 작업에서 수행 할 작업으로 생각하는 대신 다른 작업을 매개 변수로 사용하는 작업으로 생각하십시오. 예를 들어, 작업을 할 수 있습니다 작업이 나중에 실행하기위한 다른 작업을 대기열에하는 것입니다 먹으 렴 :

class WorkProcessor 
{ 
    public Action<Action<WorkItem>> WorkScheduler { get; set; } 

    public void ScheduleWork(WorkItem workItem) 
    { 
     WorkScheduler(ProcessWork); 
    } 

    public void ProcessWork(workItem) 
    { 
     //... 
    } 
} 
0

Action<Action<T>> 같은 기능의 (a에 위임) 다른 소요 기능 A (A와 위임) 자사의 논의. 그런 다음 "고차 함수"는 로깅 등을 사용하여 인수를 여러 번 호출 할 수 있습니다. 이러한 함수를 사용하면 프로그램 논리를 캡슐화하고 전달할 수 있습니다.

다음은 간단한 예제입니다.이 예제에서는 Main()에서 함수 호출을 기록할지 여부를 선택하며, 해당 선택 항목의 구현은 실제 작업자 함수에서 볼 수 없습니다. 구성 플래그를 전달하는 대신 선택 사항을 캡슐화하는 상위 순서 함수를 전달합니다.

void Run(Action<int> fn, int x) 
{ 
    fn(x); 
} 

void RunAndLog(Action<int> fn, int x) 
{ 
    print("before " + x); 
    fn(x); 
    print("after " + x); 
} 

void InvokeWorkerTenTimes(Action<Action<int>> gn, Action<int> fn) 
{ 
    // fn is WHAT to do 
    // gn is HOW to do it! 
    for(int i=0; i<10; i++) 
     gn(fn, i); 
} 

void DoWork(int x) 
{ 
}  

void Main() 
{ 
    if(LoggingEnabled) 
     InvokeWorkerTenTimes(RunAndLog, DoWork); 
    else 
     InvokeWorkerTenTimes(Run, DoWork);  
}