【问题标题】:What to use? delegate, event, or Func<T>?用什么?委托、事件或 Func<T>?
【发布时间】:2011-04-08 21:24:27
【问题描述】:

我想为类库中的对象提供“输出”消息的能力,而不用担心它是如何输出的。类库可用于控制台应用程序、WinForm 或 WPF Windows 应用程序或网页。

我最初决定使用委托来处理这个问题。我使用类实现了这一点,但是当我尝试将委托放入每个这些对象所固有的接口时,编译器不喜欢委托。

我发现我可以将代理移出界面,然后能够编译,但我不确定这是否完成了我想要做的事情。它也看起来像一个杂物,所以我想问一下你们中的任何人都有不同的想法来实现这一点……

界面:

namespace Test
{
  using System;
  using System.Xml.Linq;

  public interface IAction
  {
    DisplayMessageDelegate DisplayMessage(string message);
    void Execute();
    XElement Serialize(XName elementName);
  }

  public delegate void DisplayMessageDelegate(string message);
}

从那里,我不确定如何实现这种行为:(顺便说一句,我知道这段代码不会编译......)

public class ActionClass1 : IAction
{
  // Other methods not shown...
  void Execute()
  {
    if (this.DisplayMessage != null)
    {
      this.DisplayMessage(“Hello”);
    }
  }
}

public class ConsoleClass
{
  ActionClass1 class1 = new ActionClass1();
  class1.DisplayMessage = { x =>  Console.WriteLine(x); };
}

public class WinFormClass
{
  ActionClass1 class1 = new ActionClass1();
  Class1.DisplayMessage = {x => DisplayTextBox.Text = x; };
}

【问题讨论】:

    标签: c# events lambda delegates


    【解决方案1】:

    如果您希望能够连接多个代表以响应对Execute 的单个调用,我肯定会使用event。如果您只想连接单个操作,请使用 ActionFunc 委托。

    对于您的示例,Action 代表之一应该可以工作。在您的情况下,它将是 Action&lt;string&gt;,因为您的委托接受一个字符串参数。 Action 只是一个接受零个或多个参数并返回 void 的委托。您似乎没有返回任何东西,所以这就是我建议 Action 的原因。

    如果您的委托需要返回某些内容,您只想使用Func&lt;TResult&gt;FuncAction 之间的区别在于 Func 代表有返回类型,而 Action 代表没有。这些委托中的任何一个都有通用版本,最多可以接受 16 个左右的参数。

    如果您需要在委托上超过 16 个参数,您可能需要重新考虑设计:)

    【讨论】:

    • 应该提到,如果你需要比参数更复杂的东西,ref/out...Action/Func 将不起作用。另一个“好处”是您可以适当地命名参数(智能感知)。话虽如此,我也会使用 Action.
    【解决方案2】:

    您可以使用Action&lt;string&gt; 执行此操作。

    你不会想使用Func&lt;T&gt;,因为这是定义一个不带参数但返回一个类型为 T 的单一值的委托。另一方面,Action&lt;T&gt; 是一个只带一个参数的委托键入 T。

    我建议尝试:

    public interface IAction
    {
        Action<string> DisplayMessage { get; set; }
    
        void Execute();
        XElement Serialize(XName elementName);
    }
    

    一旦您(完全)实现了这个接口,您就可以通过以下方式使用它:

    public class ConsoleClass
    {
        public void SomeMethod()
        {
            ActionClass1 class1 = new ActionClass1();
            class1.DisplayMessage = x => Console.WriteLine(x);
        }
    }
    

    或者:

    public class ConsoleClass
    {
        public void SomeMethod()
        {
            ActionClass1 class1 = new ActionClass1();
            class1.DisplayMessage = this.Print;
        }
    
        private void Print(string message)
        {
            Console.WriteLine(message);
        }
    }
    

    你可以对事件做同样的事情,但是,我会质疑这一点。您的 API 描述的是应该发生的操作,而不是您正在响应的正在发生的事件 - 因此,我不建议您使用事件。

    【讨论】:

      【解决方案3】:

      您的接口定义错误。您需要像这样指定它:

      namespace Test
      {
        using System;
        using System.Xml.Linq;
      
        public interface IAction
        {
          DisplayMessageDelegate DisplayMessage { get; set; };
          void Execute();
          XElement Serialize(XName elementName);
        }
      
        public delegate void DisplayMessageDelegate(string message);
      }
      

      然后实现接口。

      【讨论】:

        【解决方案4】:

        这里

        DisplayMessageDelegate DisplayMessage(string message);
        

        您描述了接受字符串并返回 DisplayMessageDelegate 的方法。 使用

         event DisplayMessageDelegate DisplayMessage;
        

        改为。

        【讨论】:

          【解决方案5】:

          我个人认为最好有一个抽象基类,它定义了一个名为 DisplayMessage 的抽象方法,然后通过派生该基类来扩展该基类,以改变消息显示方式的行为。

          【讨论】:

          • 我确实考虑过...我忽略了一个事实(为了简化问题)这些派生类将位于 List 集合中,我将在其中执行 ForEach 循环对每个项目执行Execute方法,根据我当时运行的应用程序类型设置“DisplayMessage”...
          【解决方案6】:

          代替:

          DisplayMessageDelegate DisplayMessage(string message);
          

          做:

          event Action<string> DisplayMessage;
          

          然后按正常使用 DisplayMessage,事件是委托。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-01-17
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2010-09-24
            相关资源
            最近更新 更多