"Action?"关键字是干什么的,是不是代替了ActionResult

What does the "Action?" keyword do, does it replace ActionResult

我看到了这段代码,我想知道 Action? 是做什么的,搜索后我在 MSDN 上看到了这个 “封装了一个只有一个参数但没有参数的方法return 一个值。" 仍然无法理解(应用程序用例)如何使用它,它是否是 ActionResult 更好的替代品

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

 public class PrisonerDilemma 
 {
     public string PrisonerName { get; private set; }
     public StrategyBase Strategy { get; private set; }
     // What is this Action keyowrd doing?
     public Action? LastAction { get; private set; }        

     public Prisoner(string name, StrategyBase strategy)
     {
        if (strategy == null)
            throw new ArgumentNullException("strategy");

        PrisonerName = name;
        Strategy = strategy;
     }

     public void Do(Action? previousActionOfAnotherPrisoner)
     {
        if (previousActionOfAnotherPrisoner == null)
            LastAction = Strategy.Init();
        else
            LastAction = Strategy.Next(previousActionOfAnotherPrisoner.Value);
     }

 }

编辑 1: 在 ASP MVC

  1. Action?关键字起什么作用?怎么样 used/leveraged.
  2. 如果 Action 不接受参数并且不 return 一个值,请帮助解释 它有什么用处 ,即通常什么时候在设计模式中使用*? passing/referring 控制器动作到子动作?
  3. 如果我想将它用作 VisitorStrategy pattern,它可以像在 C++ 中那样跨越对象边界传递吗?还是范围仅限于实例或 Class 或派生类型?

编辑 2: 感谢您的解释,现在很清楚它的功能重用。我发现 another post on SO 有助于理解 Action 与 Func 之间的区别, 但不是典型的用例应用程序 ,比如什么是实现它的好用例。例如在函数重用中,是否可以像 C++ 中那样跨对象边界传递?

Action不是关键字,是类型。 Action 类型是委托类型,这意味着它表示对函数的引用。 Action 个实例必须引用不带参数的函数和 return void。还有 Action 的通用版本,如 Action<T1, T2>,可用于引用采用多个参数的函数。每个通用参数类型代表一个参数的类型。

https://msdn.microsoft.com/en-us/library/system.action(v=vs.110).aspx

至于类型名称后的 ?,我觉得这不对。 ? 在类型之后使该类型可为空,但这只能应用于值类型。所有委托类型都是引用类型,因此任何委托都可以分配 null 作为值。据我了解,? 应用于引用类型实际上是一个编译器错误。

这是 ActionResult 类型的文档: https://msdn.microsoft.com/en-us/library/system.web.mvc.actionresult(v=vs.118).aspx

单词"action"的用法与System.Action中的用法完全不同。

Action 和ActionResult 之间没有任何关系。动作与 MVC 无关。它只是一个泛型委托类型(不是关键字),它本质上是一个 "template" 被框架广泛使用,因此他们决定创建泛型类型以便可以经常重用。

Action 最多可以为 16 个参数取 0,所有参数均为 void return 类型。 Func 是相同的,但具有 return 类型。

实际上,您可以在任何需要引用具有类似函数签名的函数的地方使用 Action。

因此,例如,假设您要创建一个将另一个方法作为参数的方法。此 "other method" 可以输入为 Action(或 Func),这样您就不必对类型进行硬编码。

如果您查看 Action documentation 中的第一个示例,这里有一个普通委托函数的示例。第二个例子使用 Action 做同样的事情:

public static void Main()
{
  Action<string> messageTarget; 

  if (Environment.GetCommandLineArgs().Length > 1)
     messageTarget = ShowWindowsMessage;
  else
     messageTarget = Console.WriteLine;

  messageTarget("Hello, World!");   
}      

private static void ShowWindowsMessage(string message)
{
   MessageBox.Show(message);      
}

在此代码中,它引用了一个带有 1 个参数和 void return 类型的函数。这可以映射到一个动作。 Console.WriteLine() 也是一种采用 1 个参数和 void return 类型的方法,因此如果将它们视为 Actions,则它们可以互换。

另一方面,

ActionResult 是一种封装来自 MVC 操作(不是 System.Action)的 returned 数据的类型。例如,如果您 return 一个 ViewResult,它派生自 ActionResult 并封装呈现 View 所需的数据。它与通用委托 Action 无关,只是名称相似。

编辑:

根据以下评论,您将使用如下操作实施预算:

public class MyBudget
{
    int _budgetId;
    int _deptId;
    public MyBudget(int budgetId, int deptId) 
    {
         _budgetId = budgetId;
         _deptId = deptId;
    }
    void CalcBudget()
    {
        // Do your budget code using _budgetId and _deptId
    }
}

public class GenericBudgetProcessor
{
    private Action _specificBudget

    public GenericBudgetProcessor(Action specificBudget)
    {
        _specificBudget = specificBudget;
    }

    public void DoTheBudget(Action specificBudget)
    {
        _specificBudget();
    }
}

那么您将在其他地方获得执行此操作的代码:

var budget = new MyBudget(1, 1);
var processor = new GenericBudgetProcessor(budget.CalcBudget);
processor.DoTheBudget();

// Do a different budget
var budget2 = new YourBudget(2, 2);
processor = new GenericBudgetProcessor(budget2.CalcBudget);
processor.DoTheBudget();

这只是您可以如何使用操作的一个示例。

或者你可以在方法中传递参数

processor.DoTheBudget(1, 2);

在这种情况下,您可以修改上面的内容以使用 Action<int, int> 而不是 Action.