2017-08-09 95 views
2

在Java JAVA回调格局,这是正常的:是否有可能实现在C#

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中,你可以创建一个接口的实例,但C#你不能?

+0

我想你使用回调给一个方法作为参数传递给另一个。在C#中,这些代码是用来代替的。 –

回答

1

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

DoWork(() => Console.WriteLine("callback called")); 

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

编辑

尤其是当我处理网络有OnSuccess,OnError的服务。

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(); 
} 
+0

但是这个更不干净,特别是当我处理具有OnSuccess,OnError的Web服务时。 – ywj7931

+0

@ ywj7931见我的编辑,这是我能想到的... –

+2

@在C#代码下手不鼓励ywj7931这样一般来说回调最接近。我们改为使用任务'await/async' – BradleyDotNET

0

/'内嵌类定义'(你在前面已经说明)Java的相当整洁的 '接口的在线实现' 也不是C#的一部分。

可能继续前进,实现监听器接口/类,并将其传递到对象,这实际上是同样的事情 - 然而,这可以得到相当详细的速度非常快,而且很多时候你真的只需要提供一个单一的无论如何回调。

C#有两个有用的工具,使生活变得更加简单:

  1. 代表
  2. 活动

代表

这是有道理的看着活动之前,了解代表。 A 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 &一个链接到)。我经常发现使用Action自己(无效的方法,不带参数),并Action<Something>(无效的方法,接受一个参数)在简单情况。

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

活动

虽然有可能建立自己的模式使用委托对象的变化进行监测,C#更进了一步,并为您提供现成的事件......

Events是一个非常便于对象整理'处理程序'委托方法,然后用一组参数调用它们。

首先定义委托类型的“处理”的方法:

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

然后通过定义一个公共事件,您可以为代表注册/注销一个到达现场。我有时前缀我的活动与“开” - 它是代码的造型问题:

public event StuffHappenedHandler OnStuff; 

是希望监控此事件的对象需要的StuffHappenedHandler委托类型签名匹配方法:

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

现在,它可以注册与OnStuff事件方法:

monitoredObject.OnStuff += ObjectStuffHandler; 

从事件中注销的委托方法,它只是简单:

monitoredObject.OnStuff -= ObjectStuffHandler; 

当涉及到通知可能正在侦听的对象时,检查空事件很重要。本次活动将是空的,如果没有什么注册:

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

我目前的设置实际上是事件驱动的,但是在我成功完成一个Web请求并继续到下一个Web请求之后,我发现它并不清楚这是一个顺序过程。为事件使用lambda更容易使其变得干净,但要取消注册lambda事件却很难。 – ywj7931

+0

如果你正在做顺序异步的事情,也许你应该花一些时间来学习Rx:https://msdn.microsoft.com/en-us/library/hh242985(v=vs.103).aspx – instantiator

+0

是的,但是在这种情况下,我需要导入我想避免的库 – ywj7931

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(); 
} 
相关问题