什么是C#中的简单组合

时间:2017-01-09 09:06:21

标签: c# delegates

根据MSDN,建议在需要简单构图时使用代表。 有人可以用一个例子来解释 Easy Composition 是什么?

3 个答案:

答案 0 :(得分:2)

这篇MSDN文章比较了某些情况下接口的使用情况与代表的使用情况。它表示代表与界面相比提供了简单的组合。这是什么意思?假设你有这样的界面:

interface ICanWrite {
    void Write();
}

现在你有两个这样的接口实例:

ICanWrite first;
ICanWrite second;

你是如何撰写的?那么,您如何获得ICanWriteWrite方法同时执行first.Writesecond.Write的新static void Main(String[] args) { Action write = null; // Action is a delegate type write += () => Console.WriteLine("one"); // first write write += () => Console.WriteLine("two"); // composition, looks quite easy compared to interfaces write(); // both delegates are executed ("one two") } 实例?不容易。

现在假设您使用委托而不是接口:

click

答案 1 :(得分:2)

一个例子会有所帮助。

想象一下,您有一个需要输出一些日志消息的类,并且您希望使用构造函数依赖注入为该类提供记录消息的方法。

您有多种选择,包括:

  1. 将包含记录消息的方法的接口传递给类构造函数。
  2. 将类直接记录消息的委托传递给类构造函数。
  3. 界面可能如下所示:

    public interface Log
    {
        void WriteLine(string message);
    
        // ... Other methods
    }
    

    因此课程可能如下所示:

    public sealed class MyClass
    {
        readonly ILog _log;
    
        public MyClass(ILog log)
        {
            _log = log;
        }
    
        public void Test()
        {
            _log.WriteLine("Test() called");
        }
    }
    

    此类现在耦合到ILog接口,在构造它时,您必须提供一个实现ILog的对象。

    如果您使用委托,则该类可能如下所示:

    public sealed class MyClass
    {
        readonly Action<string> _writeLogLine;
    
        public MyClass(Action<string> writeLogLine)
        {
            _writeLogLine = writeLogLine;
        }
    
        public void Test()
        {
            _writeLogLine("Test() called");
        }
    }
    

    现在该类不再与ILog耦合,并且在构造它时,您可以将与该委托匹配的任何方法传递给它:

    var myClass = new MyClass(Console.WriteLine);
    

    这使MyClass的构图更容易 - 因此 轻松构图

答案 2 :(得分:1)

你误解了#34;容易构图&#34; as&#34; Easy Composition&#34;,实际上它并不意味着它本身就是一个技术术语。它们只是意味着使用代理比使用接口更容易实现组合(即需要更少的工作)。

如果您已经成为.NET程序员一段时间,您可能会认识System.Action代表。您可以一瞥MSDN文章在将System.Action与界面的外观进行比较时的含义:

delegate void Action();

interface IAction
{
    void Execute();
}

代表是一个单行,而界面需要更多的输入,并且需要为该方法提供一个额外的名称。

MSDN文章的真正含义是使用委托与接口。我们假设您有一些采用回调处理程序的方法onCompleted

void DoSomethingThatTakesVeryLong(Action onCompleted)
{
    // do something that might take a while:
    …
    // notify the caller that we're done:
    onCompleted();
}

现在使用这种方法需要什么?

如果onCompleted属于委托类型,您可以编写以下内容:

DoSomethingThatTakesVeryLong(() => Console.WriteLine("Done."));

如果onCompleted属于接口类型(让我们假定上面是IAction),那么您必须将回调代码包装在实现IAction的类型中:

class DoneLogger : IAction
{
    public void Execute()
    {
        Console.WriteLine("Done");
    }
}

DoSomethingThatTakesVeryLong(new DoneLogger());

这需要做更多的工作:你需要在一个非常必要的类中包含非常简单的代码,你需要为该类提供一个名称,你需要实例化该类。现在想象一下,没有代表,你总是必须这样做......那就是很多样板代码。

我希望这能帮助您了解代表如何比接口更少的工作。