是否可以在C#中实现JAVA回调模式

时间:2017-08-09 23:08:58

标签: java c#

在Java中,这是正常的:

public class Test {
    public static void main(String[] args) throws  Exception {
        new Test().doWork(new Callback() { // implementing class            
            @Override
            public void call() {
                System.out.println("callback called");
            }
        });
    }

    public void doWork(Callback callback) {
        System.out.println("doing work");
        callback.call();
    }

    public interface Callback {
        void call();
    }
}

我想知道C#中是否存在等价?我在C#中进行了实验,但在doWork()函数之后有问题实例化的新接口。是因为在JAVA中你可以创建一个接口的instacne而C#你不能吗?

3 个答案:

答案 0 :(得分:1)

不一样,但类似的方法(传递委托)将是:

DoWork(() => Console.WriteLine("callback called"));
void DoWork(Action callback)
{
    Console.WriteLine("doing work");
    callback();
}

修改

  

尤其是当我处理具有OnSuccess,OnError的Web服务时。

DoWork(new MyResult() {
    OnSuccess = () => Console.WriteLine("Success"),
    OnError = ()=>Console.WriteLine("Error") }
);
public class MyResult
{
    public Action OnSuccess { set; get; }
    public Action OnError { set; get; }
}

void DoWork(MyResult callback)
{
    Console.WriteLine("doing work");
    callback.OnSuccess();
}

答案 1 :(得分:0)

Java相当简洁的'内联实现'/'内联类定义'(您已在上面说明)不是C#的一部分。

可以继续实现监听器接口/类并将它们传递给对象,这实际上是同样的事情 - 但是,这可能非常快速,并且通常你真的只想要无论如何都要提供一个回调。

C#有两个有用的工具,可以让生活更轻松:

  1. 代表
  2. 活动
  3. <强>代表

    在查看事件之前理解代表是有意义的。 Delegate是一种将方法作为变量或参数传递的简洁方法。

    您可以定义委托类型(如果您愿意):

    public delegate void AMethodThatHandlesAnInteger(int theInt);
    

    然后将它们用作方法的参数:

    public void doStuffAndThenCallADelegate(AMethodThatHandlesAnInteger theDelegate)
    {
      ...
      theDelegate(4);
    }
    

    或者,通常情况下,使用已存在的预定义委托之一更容易:

    public void doStuffAndThenCallADelegate(Action<int> theDelegate)
    {
      ...
      theDelegate(4);
    }
    

    Delegates can be generic - 这使它们成为一个非常强大的工具。

    有许多delegates defined by the framework,(由方便的Q&amp; A链接到列出)。在简单的情况下,我经常发现自己使用Action(void方法,不带参数)和Action<Something>(void方法,只接受一个参数)。

    Func<Something,Else>允许返回类型,从那里变得更有趣! Actions和Funcs允许0-4个参数(不包括Func的返回类型)。

    <强>事件

    虽然可以使用委托构建自己的模式来监视对象更改,但C#更进一步为您提供现成的事件......

    Events是一个非常方便的方法,可以让对象整理'handler'委托方法,然后用一组参数调用它们。

    首先定义'handler'方法的委托类型:

    public delegate void StuffHappenedHandler(int stuffs, string summary);
    

    然后,通过定义公共事件,您可以为委托的注册/注销创建一个可到达的字段。我有时会在事件前面添加'On' - 这是代码样式的问题:

    public event StuffHappenedHandler OnStuff;
    

    希望监视此事件的对象需要一个与StuffHappenedHandler委托类型签名匹配的方法:

    public void MonitoredObjectStuffHandler(int howMany, string summary)
    {
      ...
    }
    

    现在它可以使用OnStuff事件注册该方法:

    monitoredObject.OnStuff += ObjectStuffHandler;
    

    要从事件中取消注册委托方法,它就是这么简单:

    monitoredObject.OnStuff -= ObjectStuffHandler;
    

    在通知可能正在侦听的对象时,检查null事件非常重要。如果没有注册,该事件将为null:

    if (OnStuff != null)
      OnStuff(4, "four things");
    

答案 2 :(得分:0)

如果您真的想在C#中执行与此类似的操作,可以使用Moq这是一个单元测试框架(通常仅用于单元测试,而不是生产代码)。我不建议实际执行此操作,因为其他人建议C#具有替代模式,以更好的方式实现您尝试的相同目标,例如Delegates或async / await。但是,通过Moq可以创建接口实例,这对于C#中的单元测试非常有用(特别是如果你使用IoC)。

public class Test 
{
    public static int Main(string[] args)
    {
        var mockCallback = new Mock<ICallback>();
        mockCallback.Setup(t=>t.Call()).Callback(() =>
        { 
            Console.WriteLine("callback called");
        });
        new Test().doWork(mockCallback.Object);
    }

    public void DoWork(ICallback callback) 
    {
        Console.WriteLine("doing work");
        callback.Call();
    }
}

public interface ICallback
{
    void Call();
}