32

如果我搜索,我肯定会得到展示什么是代表和动作的示例。我已经阅读了提供代表示例的基本书籍。

但我想知道的是它们在现实世界中的用途。请不要给出 Hello World 示例或 Animal 类,它们太基础了

例如:

  1. 它们之间有什么区别
  2. 何时使用委托或操作
  3. 何时不使用委托或操作
  4. 当他们可以过度杀戮时
4

5 回答 5

34

Action 一个Delegate。它是这样定义的:

public delegate void Action();

您可以像创建抽象方法一样创建自己的委托类型;你写了签名但没有实现。然后,您可以通过引用方法来创建这些委托的实例。

class Program
{
    public static void FooMethod()
    {
        Console.WriteLine("Called foo");
    }

    static void Main()
    {
        Action foo = FooMethod; // foo now references FooMethod()
        foo(); // outputs "Called foo"
    }
}
于 2012-07-07T16:31:04.257 回答
22

当您定义委托时,您实际上是在定义方法的签名(返回类型和参数)。

一个 Action 是一个已经定义好的委托(void return 并且没有 args)。

public delegate void Action()

你可以去定义,自己看看。或者在文档中。 http://msdn.microsoft.com/en-us/library/system.action.aspx

当我要查找的方法的签名与支持的签名匹配时,我几乎总是使用现有的通用委托(其中一个操作是其中一个)。使用泛型委托的一个好处是它们是众所周知的。大多数开发人员都知道 Action 是无效/无效的。如果我要定义自己的 Action 版本,每个人都需要查找它的签名,而我只是复制了一些已经存在的东西。

例如... 操作碰巧有点少见,因为 void/void 方法的目的只能用于突变。Func 很常见(也是通用委托)。在整个框架中都有使用它的示例,尤其是在 linq 中。以 .where 为例。http://msdn.microsoft.com/en-us/library/bb534803.aspx。这是一个 Func,这意味着它将您正在处理的集合类型的元素作为参数并返回一个布尔值。在具有 Func 返回 true 的 where 语句的上下文中,意味着将其包含在结果中,反之亦然。

public static IEnumerable<TSource> Where<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate
)
于 2012-07-07T16:19:57.387 回答
11

由于 Kenneth & Siege 已经指出了代码和 MSDN,我将尝试填写真实世界的示例。

考虑一个定义“移动”的委托。

现实世界中的“Action”代表将是“Run”或“Walk”。您不关心您的移动速度、您采取的路线或报告移动所需的时间。

例如,非 Action 委托可以定义您运行的速度并返回完成它所花费的时间。

public delegate void MoveAction();
public delegate int MoveDelegate(int speed);

扩展围攻的例子..

class Program
{
    public static void Run()
    {
        Console.WriteLine("Running");
    }

    public static int RunAtSpeed(int speed)
    {
         // logic to run @ speed and return time
         Console.WriteLine("Running @ {0}", speed); 
         return 10;
    }

    public static int WalkAtSpeed(int speed)
    {
         // logic to walk @ speed and return time
         Console.WriteLine("Walking @ {0}", speed); 
         return 20;
    }

    static void Main()
    {
        Action foo = Run; 
        foo(); 

        MoveDelegate run = RunAtSpeed;
        int result1 = run(5);

        MoveDelegate walk = WalkAtSpeed;
        int result2 = walk(1);
    }
}
于 2012-07-07T18:20:06.133 回答
5

什么是Action: 很简单Action,Func<>,Predicate 都是delegate 类型。

为什么需要Action: Action封装了不同数量的参数和不同类型的返回类型,在很多情况下足以满足应用开发的需要。这些在 System 命名空间中提供。您可以自由创建自己的委托。

请注意,有 17 种不同类型的 Action 和 Func,每种都有零到 16 个参数化的通用参数。

动作总是没有返回值。Func 有一个参数化的泛型返回类型。

恕我直言,不需要将谓词委托定义为它真正等同于接受 arg 并返回 bool 的 Func。

于 2015-03-19T04:32:19.553 回答
5

“Console.WriteLine”用户已在较早的答案中提供了反复请求的真实世界示例代码。

至于为什么提供它,据我了解,Action 是一种省去继续定义自己的新代表的方法。由于它是特定签名类型的预定义委托,因此您可以省去为每个预期目的创建不同委托的麻烦。您只需使用预定义的 Action 委托来指向您的方法并运行它们。Func 代表也是如此。

更多的是一种便利,而不是真正的新功能。帮助您的代码简短易懂,减少麻烦。

至于你的点问题,

  1. 它们之间有什么区别

没有不同。Action 是一个预定义的委托,旨在为您省去重复定义新委托的麻烦。

  1. 何时使用委托或操作

通常,委托(和操作)用于需要具有表驱动功能的地方。即,可能是对应于某些特定要求的方法字典。请注意,在这里使用 Action 可以轻松更改最终调用的方法,以动态指向其他方法(可能基于用户选择的某些设置?)


class Program
{
    static void Main()
    {
     Dictionary<string, Action> dict = new Dictionary<string, Action>();
     dict["loadFile"] = new Action(LoadFile);
     dict["saveFile"] = new Action(SaveFile);

     dict["loadFile"].Invoke();
     dict["saveFile"].Invoke();
    }

    static void SaveFile()
    {
     Console.WriteLine("File saved!");
    }

    static void LoadFile()
    {
     Console.WriteLine("Loading File...");
    }
}

另一个典型的用法是回调方法。例如,您使用 BubbleSort 类,将比较器方法作为委托传递给该类,BubbleSort 类将使用该委托来允许您的代码定义比较逻辑,同时处理其他所有事情。这也可以从您启动的线程中使用,并且当需要将一些中间操作通知给您的代码时,该线程会调用委托。

您可以参考这篇 SO 帖子以查看上述的一个很好的示例。 https://stackoverflow.com/a/3794229/1336068

  1. 何时不使用委托或操作

我能想到在情况需要时不使用它们的唯一原因是,如果您的代表将在短时间内被呼叫数百万次。这涉及到一点点开销,如果这导致应用程序滞后,那么您可能必须找到一种更好的方法来解决这个问题,使用直接引用您的函数,而不是通过委托。

  1. 当他们可以过度杀戮时

当您在没有任何实际需要的情况下免费使用它们时。否则,在大多数情况下,它们可以成为解决上述情况的一种优雅方式。

另外,请阅读此 SO 答案以查看普通方法和委托之间的区别,以便更好地了解在何处使用委托/操作/func https://stackoverflow.com/a/17380580/1336068

于 2016-11-02T04:35:11.177 回答