Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/292.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 通过各种技巧编写回调的指南_C#_Design Patterns - Fatal编程技术网

C# 通过各种技巧编写回调的指南

C# 通过各种技巧编写回调的指南,c#,design-patterns,C#,Design Patterns,我在决定是否使用时感到困惑 多态(通过重写虚拟方法a)方法 委托类型参数化方法B 事件C 使用单个方法D实现接口的类的实例。Java的把戏 在编写回调时 using System; namespace CallBack { interface IOptional { void D(); } class Base { protected virtual void A() => Console.WriteLine(

我在决定是否使用时感到困惑

  • 多态(通过重写虚拟方法
    a
    )方法
  • 委托类型参数化方法
    B
  • 事件
    C
  • 使用单个方法
    D
    实现接口的类的实例。Java的把戏
在编写回调时

using System;

namespace CallBack
{
    interface IOptional
    {
        void D();
    }

    class Base
    {
        protected virtual void A() => Console.WriteLine("Base's extra jobs.");
        public void Do(Action B = null, IOptional optional = null)
        {
            Console.WriteLine("Base's main jobs.");

            // and call the optional jobs
            A();
            B?.Invoke();
            C?.Invoke();
            optional?.D();
        }
        public event Action C;
    }


    class Derived : Base
    {
        protected override void A()
        {
            base.A();

            Console.WriteLine("Derived's extra jobs.");
        }
    }

    class Optional : IOptional
    {
        public void D()
        {
            Console.WriteLine("D");
        }
    }

    class Test
    {
        static void Main()
        {
            Derived d = new Derived();
            d.C += () => Console.WriteLine("C");
            d.Do(() => Console.WriteLine("B"), new Optional());
        }
    }
}
问题
敏捷程序员有什么常用的指导原则吗?

这三个用例在我看来非常不同:)

核心思想是“你想让谁知道这件事”

如果您想让每个人都能订阅它,请使用
事件
。这也是我在处理回调方面的大部分.NET经验

using System;

namespace CallBack
{
    interface IOptional
    {
        void D();
    }

    class Base
    {
        protected virtual void A() => Console.WriteLine("Base's extra jobs.");
        public void Do(Action B = null, IOptional optional = null)
        {
            Console.WriteLine("Base's main jobs.");

            // and call the optional jobs
            A();
            B?.Invoke();
            C?.Invoke();
            optional?.D();
        }
        public event Action C;
    }


    class Derived : Base
    {
        protected override void A()
        {
            base.A();

            Console.WriteLine("Derived's extra jobs.");
        }
    }

    class Optional : IOptional
    {
        public void D()
        {
            Console.WriteLine("D");
        }
    }

    class Test
    {
        static void Main()
        {
            Derived d = new Derived();
            d.C += () => Console.WriteLine("C");
            d.Do(() => Console.WriteLine("B"), new Optional());
        }
    }
}
通过使用多态性方法,您只允许子类了解事件。如果其他对象想在发生时执行某些操作,它就不能,因为它不是子类,也不能重写该方法


通过使用委托参数方法,可以将订阅者的数量限制为1。任何调用方都可以订阅该事件,但订阅方事件现在是一对一关系。

否,请不要迁移此问题。它将被关闭。需要考虑的是:如果问题不涉及一个推,而是一个拉动,那么这个问题会如何不同?当您有一个必须读取的值为
X
的类时,您是否实现了(1)字段、(2)属性、(3)带有属性的接口、(4)方法、(5)带有方法的接口?我认为这个问题的答案应该是“这取决于进行拉取的代码的需要”。推动是一样的;客户的需求推动了设计。@EricLippert:非常感谢。@MoneyOrientedProgrammer您不应该真的编辑您的问题来询问新的东西。。。Java的“把戏”之所以存在,是因为Java没有委托。C#有委托,因此您总是选择使用委托参数或事件。这就是说,Java8现在有了lambdas,所以Java的技巧甚至在Java中也不太常见。