Delegate& amp;在C#中采取行动

时间:2012-07-07 16:17:27

标签: c#

如果我搜索过,我肯定会得到一个显示什么是代表和行动的例子。 我已经阅读了基本书籍,给出了代表的例子。

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

例如:

  1. 他们之间有什么区别
  2. 何时使用代理人或行动
  3. 何时不使用代表或行动
  4. 什么时候可以过度杀人

5 个答案:

答案 0 :(得分:25)

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"
    }
}

答案 1 :(得分:19)

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

Action是一个已经定义的委托(void return and no args)。

public delegate void Action()

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

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

例如......由于void / void方法的目的只能用于变异,因此动作恰好有点罕见。 Func很常见(也是通用委托)。在整个框架中都有它的用法示例,特别是在linq中。比如看看。的地方。 http://msdn.microsoft.com/en-us/library/bb534803.aspx。它是一个Func意味着它将您正在处理的集合类型的元素作为参数并返回一个bool。在具有Func返回true的where语句的上下文中,意味着将其包含在结果中,反之亦然。

public static IEnumerable<TSource> Where<TSource>(
    this IEnumerable<TSource> source,
    Func<TSource, bool> predicate
)

答案 2 :(得分:7)

自Kenneth&amp;围攻已经指出了代码&amp; MSDN我将尝试填写现实世界的例子。

考虑一个定义&#34;移动&#34;。

的代表

&#39;行动&#39;在现实世界中的代表将是&#39; Run&#39;或者&#39; Walk&#39;。你不关心你移动的速度,你走的路线或报告移动的时间。

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

答案 3 :(得分:3)

什么是行动 相当简单的Action,Func&lt;&gt;,Predicate都属于委托类型。

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

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

操作始终没有返回值。 Func有一个参数化的泛型返回类型。

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

答案 4 :(得分:1)

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

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

真的更方便,而不是实际的新功能。帮助您保持代码简短易懂,减少麻烦。

就你的观点问题而言,

  1. 他们之间有什么区别
  2. 没有区别。 Action是一个预定义的委托,旨在为您省去重复定义新委托的麻烦。

    1. 何时使用代理或操作
    2. 通常,委托(和操作)用于需要具有表驱动功能的位置。即,可能是对应于某些特定要求的方法的字典。请注意,在此处使用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. 何时不使用代理或操作
      2. 我认为在情况需要时不使用它们的唯一原因是,如果你的代表将在短时间内被召唤数百万次。涉及到一些轻微的开销,如果这导致应用程序延迟,那么您可能必须找到一种更好的方法来解决此问题,使用直接引用您的函数,而不是通过委托。

        1. 什么时候可以过度杀人
        2. 当你无偿地使用它们时,没有任何实际需要。否则,在大多数情况下,它们可以是解决上述情况的优雅方式。

          另外,请阅读此SO答案以了解正常方法之间的区别,委托以更好地了解委托人/ action / func的使用位置 https://stackoverflow.com/a/17380580/1336068