2013-03-23 97 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