"Action<Action<T>>"在概念上代表什么?

4
我了解Action代表对对象执行的操作,但在一些代码库中,我看到参数声明为>>,我很难理解在另一个操作上执行操作是什么意思。
因此,概念上,>>代表什么,您能否提供一个使用它的示例?
4个回答

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);

一般来说,任何接收函数本身lambda的工作lambda都会使用这种模式。

3
一个 Action<Action<T>> 是一个委托,它将一个 Action<T> 作为其参数。这将允许您传递一个委托,当调用时,将传递第二个委托(类型为 Action<T>)。
然而,这种用法应该相当少见。通常,您可以只使用单个 Action<T> 并将其传递。我唯一能想到需要使用此方法的地方是在存储委托集合的情况下。
例如,假设您有一系列操作可用于 Person 类。这可以定义为: List<Action<Person>> actions;。给定此列表,如果您想要使用 List<T>.ForEach 来执行所有这些方法来处理某个特定人员,只要符合某些条件,您可以像这样做:
Person person = GetPersion();
actions.ForEach( action => 
   {
       if (person.Foo)
            action(person); // Call the action on the person
   });

上述 lambda 表达式将成为一个 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>> 是一个(委托到委托的)函数,它以另一个(委托到委托的)函数作为其参数。这样一个“高阶函数”可以多次有条件地调用其参数,并进行日志记录等操作。这种函数允许您封装程序逻辑并传递它。

这里是一个简单的例子,其中选择是否记录函数调用在 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 );     
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接