을 나타냅니다. 액션은 객체에 대해 수행 할 액션을 나타내지 만, 몇 가지 코드베이스에서는 Action<Action<T>>
으로 선언 된 매개 변수를 보았으며 수행 할 액션을 이해하려고 애썼지 만 다른 행동이 의미합니다.개념적으로 무엇을 할 것인가 <Action<T>>는
그래서 개념적으로는 Action<Action<T>>
이 무엇을 나타 냅니까? 하나를 사용하는 예제를 제안 할 수 있습니까?
을 나타냅니다. 액션은 객체에 대해 수행 할 액션을 나타내지 만, 몇 가지 코드베이스에서는 Action<Action<T>>
으로 선언 된 매개 변수를 보았으며 수행 할 액션을 이해하려고 애썼지 만 다른 행동이 의미합니다.개념적으로 무엇을 할 것인가 <Action<T>>는
그래서 개념적으로는 Action<Action<T>>
이 무엇을 나타 냅니까? 하나를 사용하는 예제를 제안 할 수 있습니까?
끝으로 시작하여 패턴을 사용하여 긴 스레드가 주 스레드에서 실행되는 동안 다중 스레드 "진행률"대화 상자를 만듭니다. 진도 막대 및 상태 텍스트를 업데이트하는 방법을 알고있는 람다 (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);
일반화,이 패턴을 사용 함수 자체에서 람다를 수신하는 작업자 람다.
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 루프를 권장합니다.이 방법이 어떻게 발생 하는지를 보여주기위한 것입니다.)
다른 작업에서 수행 할 작업으로 생각하는 대신 다른 작업을 매개 변수로 사용하는 작업으로 생각하십시오. 예를 들어, 작업을 할 수 있습니다 작업이 나중에 실행하기위한 다른 작업을 대기열에하는 것입니다 먹으 렴 :
class WorkProcessor
{
public Action<Action<WorkItem>> WorkScheduler { get; set; }
public void ScheduleWork(WorkItem workItem)
{
WorkScheduler(ProcessWork);
}
public void ProcessWork(workItem)
{
//...
}
}
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);
}