8

我最近开始使用 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();
    }
}

编辑:我的问题是关于类的simulatEvent方法TestEvent,如果 C# 可以执行这样的操作。

我想知道是否有办法用 C# 做类似的事情(在simulateEvent方法中实例化接口)以及实际调用的是什么。谢谢!

4

2 回答 2

6

呜呜……好吧,请允许我概括一下:

所以在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 void Main(string[] args)
{
    Func<int> returns42 = () => 42;
    Func<string,bool> amIPretty = name => name == "jerkimball";
    Action<int> foo = x => {};
}

现在,正如其他人所提到的,在处理事件时,您通常会在 Java 端看到这种模式——在 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();
 }

请注意,我们也可以给它一些具有相同“形状”的东西:

 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();
    }
}
于 2013-03-23T00:32:05.753 回答
2

编辑:看起来你的问题是关于匿名接口实现而不是事件。您可以使用内置Action委托类型而不是您的Event接口。

然后,您可以Action使用 lambda 表达式进行实例化。您的代码如下所示:

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

您可以使用delegate语法而不是使用() => { .. .}ie delegate() { ... }in simulateEvent

C# 不支持匿名接口实现,所以如果你的接口有多个方法,那么你必须在某个地方定义一个具体的类。根据使用情况,您可以让此类包含您可以在创建时提供的委托属性,例如

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

然后,您可以像这样创建它:

var anon = new Delegates
{
    Event = () => { ... },
    GetValue = () => "Value"
}
于 2013-03-23T00:08:15.650 回答