2017-08-09 129 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(); 
} 
相關問題