2013-03-23 100 views
3

我最近開始使用C#,並且我想找到與此等效的方法。我不知道這是叫什麼,所以我會簡單地通過代碼展示給你。C#相當於創建實現接口的匿名類

使用Java,我能創造像這樣的接口:在方法的參數

public interface Event { 
    public void execute(); 
} 

而且通過這個接口像這樣:

public class TestEvent { 
    ArrayList<Event> eventList = new ArrayList<Event>(); 

    public void addEvent(Event event){ 
     eventList.add(event); 
    } 

    public void simulateEvent(){ 
     addEvent(new Event() { 
      public void execute(){ 
       //functionality 
      } 
     }); 
    } 

    public void processEvents(){ 
     for(Event event : eventList) 
      eventList.execute(); 
    } 
} 

編輯:我的問題是圍繞從TestEvent類的simulatEvent方法,如果這樣的行動是可能的與C#。

我想知道是否有辦法用C#做類似的事情(在simulateEvent方法中實例化接口)以及實際調用了什麼。謝謝!

+0

如果它是事件和事件處理,看.. [在C#活動(http://msdn.microsoft.com/en-us/library/awbftdfh.aspx)。整個構造以不同的「C#方式」完成。你會在你的閱讀中遇到代表(即回調函數)和MulticastDelegate(即多個事件處理程序是如何綁定的)。 – 2013-03-23 00:07:30

+0

這是一個[匿名類](http://docs.oracle.com/javase/tutorial/java/javaOO/anonymousclasses.html),沒有,這不適用於C#中的接口。 – 2013-03-23 00:10:19

+0

你想要處理事件還是要求實例化一個接口(在你的simulateEvent代碼中)? – 2013-03-23 00:11:17

回答

4

汪...好,請允許我歸納了一下:

所以在Java中,你需要一種方法來繞過功能。 Java本身並不支持函數作爲一等公民,這是執行匿名類的一個原因 - 可以內聯聲明並傳遞(作爲接口)到方法/其他類然後調用的函數的打包組這些功能。

在C#中,函數是一等公民,可以聲明爲DelegatesFunc<>sAction<>s。讓我們嘗試比較(不爽):

某種的Java-Y結構的(我的Java的年代久遠,所以大家多多包涵):

public interface IDoSomething { 
    public int Return42(); 
    public bool AmIPrettyOrNot(string name); 
    public void Foo(); 
} 

public void Main(String[] args) { 
    DoStuff(new IDoSomething() { 
     public int Return42() { return 42; } 
     public bool AmIPrettyOrNot(string name) { return name == "jerkimball"; } 
     public bool Foo(int x) { ... } 
    }); 
} 

public void DoStuff(IDoSomething something) { ... } 

的這個C#中的(很粗糙),相當於將

public class Foo 
{ 
    // define the shape of our event handler 
    public delegate void HandlerForBarEvent(object sender, EventArgs args); 
    // declare our event 
    public event HandlerForBarEvent BarEvent; 

    public void CallBar() 
    { 
     // omitted: check for null or set a default handler 
     BarEvent(this, new EventArgs()); 
    } 
}  

public void Main(string[] args) 
{ 
     var foo = new Foo(); 
     // declare the handler inline using lambda syntax 
     foo.BarEvent += (sender, args) => 
     { 
      // do something with sender/args 
     } 
     foo.CallBar(); 
} 
: - :是同樣在C#側現在

public void Main(string[] args) 
{ 
    Func<int> returns42 =() => 42; 
    Func<string,bool> amIPretty = name => name == "jerkimball"; 
    Action<int> foo = x => {}; 
} 

,如其他人所說,你通常與事件的處理打交道時看到在Java端這種模式

請注意,我們也可以給它使用相同的「形」的東西:

public void MyHandler(object sender, EventArgs args) 
{ 
    // do stuff 
} 
public void Main(string[] args) 
{ 
     var foo = new Foo(); 
     // that method above is the same "shape" as HandlerForBarEvent 
     foo.BarEvent += MyHandler; 
     foo.CallBar(); 
} 

但它在Java中也被用來定義做,如果沒有記錯(即Runnable)什麼帖子 - 我們能做的事情這個問題,以及在C#:

var thread = new Thread((Action)(() => 
    { 
     // I'm the threads "run" method! 
    }); 
thread.Start(); 

現在,其他的東西 - 枚舉:

public void processEvents(){ 
    for(Event event : eventList) 
     eventList.execute(); 
} 

C#有同樣的想法,只是所謂的不同:

public void processEvents() 
{ 
    // edit: derp, 'event' is a keyword, so I'm 
    // renaming this, since I won't get into why 
    // you could also use @event... 
    foreach(var evt in eventList) 
    { 
     evt.Execute(); 
    } 
} 
+1

他們並不是真正的首次公民。他們更像是從F#(Action,Func,Linq(monads),Lambdas)採用的二等公民。代表並不是真正的函數,它們是用來引用函數的特殊類。 – Romoku 2013-03-23 00:36:33

+1

@Romoku哦,你只是尼特採摘:) - 是的,你是正確的;不要問我有多少次嘗試在單目錄聲明中擊敗C#編譯器類型推斷提交... – JerKimball 2013-03-23 00:40:28

2

編輯:它看起來像你的問題是關於匿名接口實現,而不是事件。您可以使用內置的Action代理類型代替Event接口。

然後您可以使用lambda表達式Action實例。你的代碼是這樣:

public class TestEvent 
{ 
    List<Action> eventList = new List<Action>(); 

    public void addEvent(Action event){ 
     eventList.add(event); 
    } 

    public void simulateEvent(){ 
     addEvent(() => { 
     }); 
    } 

    public void processEvents(){ 
     for(Action event : eventList) 
      event(); 
    } 
} 

可以使用的,而不是在simulateEvent使用() => { .. .}delegate() { ... }delegate語法。

C#不支持匿名接口實現,所以如果你的接口有多個方法,那麼你必須在某個地方定義一個具體類。根據使用情況,您可以讓此類包含創建時可以提供的委託屬性,例如,

public class Delegates 
{ 
    public Action Event { get; set; } 
    public Func<string> GetValue { get; set; } 
} 

然後,您可以創建它想:

var anon = new Delegates 
{ 
    Event =() => { ... }, 
    GetValue =() => "Value" 
} 
+0

我認爲重點是在Java中你可以實例化一個接口。 – 2013-03-23 00:09:56

+0

@ ta.speot.is覆蓋實例化委託。 – 2013-03-23 00:11:15

+0

@ ta.speot.is - 在Java中,接口實際上只是用於定義回調方法。在C#中,這些都是使用委託類型完成的,並且事件是在這些之上構建的。 – Lee 2013-03-23 00:11:18