用什么?委托,事件或Func <T>?

Jul*_*ing 7 c# events lambda delegates

我想为类库中的对象提供"输出"消息的能力,而不必担心它是如何输出的.类库可以在控制台应用程序,WinForm或WPF窗口应用程序或网页中使用.

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

我发现我可以将代理移出界面然后能够编译但是我不确定这是否能完成我想要做的事情..它看起来像是一个kludge所以我想问你们是否有人有不同的想法来实现这一目标......

界面:

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);
}
Run Code Online (Sandbox Code Playgroud)

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

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; };
}
Run Code Online (Sandbox Code Playgroud)

And*_*ite 12

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

对于您的示例,其中一个Action代表应该工作.在您的情况下,它将是Action<string>您的委托采用字符串参数.An Action只是一个委托,它接受零个或多个参数并返回void.看来你没有返回任何东西,所以这就是我建议的原因Action.

Func<TResult>如果您的委托需要返回某些内容,您只想使用a .之间的区别FuncActionFunc代表有一个返回类型,Action代表没有.这些代理中的任何一个都具有泛型版本,最多可以包含16个左右的参数.

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


Ree*_*sey 7

你可以这样做Action<string>.

你不想使用Func<T>,因为这是定义一个不带参数但只返回类型为T的值的 Action<T>委托,另一方面,是一个委托,它接受一个类型为T的参数.

我建议尝试:

public interface IAction
{
    Action<string> DisplayMessage { get; set; }

    void Execute();
    XElement Serialize(XName elementName);
}
Run Code Online (Sandbox Code Playgroud)

完全实现此接口后,您可以通过以下方式使用它:

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

要么:

public class ConsoleClass
{
    public void SomeMethod()
    {
        ActionClass1 class1 = new ActionClass1();
        class1.DisplayMessage = this.Print;
    }

    private void Print(string message)
    {
        Console.WriteLine(message);
    }
}
Run Code Online (Sandbox Code Playgroud)

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