【问题标题】:C# equivalent of creating anonymous class that implements an interfaceC# 相当于创建实现接口的匿名类
【发布时间】:2013-03-23 00:05:28
【问题描述】:

我最近开始使用 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 方法中实例化接口)以及实际调用的内容。谢谢!

【问题讨论】:

  • 如果是用于事件和事件处理,请参阅..Events in C#。整个构造以不同的“C# 方式”完成。您会在阅读中遇到委托(即回调函数)和 MulticastDelegate(即如何绑定多个事件处理程序)。
  • 这是一个anonymous class,不,它不适用于 C# 中的接口。
  • 您想处理事件还是要求实例化接口的等效项(在您的模拟事件代码中)?
  • 顺便说一句:我投票以“不是真正的问题”结束。请说/问你的意思。发布的代码有许多结构,并没有隔离任何特定的问题/问题。

标签: java c# interface anonymous-class


【解决方案1】:

Woof...好吧,请允许我概括一下:

所以在 Java 中,您需要一种方法来传递函数。 Java 本身并不支持作为一等公民的函数,这是实现 匿名类 背后的一个原因 - 封装的函数组可以内联声明并(作为接口)传递给方法/其他然后将调用这些函数的类。

在 C# 中,函数是一等公民,可以声明为 DelegatesFunc&lt;&gt;sAction&lt;&gt;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();
    }
}

【讨论】:

  • 好吧,他们并不是真正的第一公民。它们更像是从 F#(Action、Func、Linq (monads)、Lambdas)中采用的二等公民。委托并不是真正的函数,它们是用于引用函数的特殊类。
  • @Romoku 哦,你只是在挑剔:) - 是的,你是对的;不要问我有多少次试图在单子声明期间击败 C# 编译器类型推断提交...
【解决方案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();
    }
}

您可以使用delegate 语法代替() =&gt; { .. .},即 delegate() { ... }simulateEvent

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

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

然后你可以像这样创建它:

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

【讨论】:

  • 我认为关键是在java中你可以实例化一个接口。
  • @ta.speot.is 涵盖了实例化委托。
  • @ta.speot.is - 在 Java 中,接口实际上只是用于定义回调方法。在 C# 中,这些是使用委托类型完成的,并且事件是在它们之上构建的。
  • 如果界面更复杂,这会崩溃。
  • @ta.speot.is - “更详细”是什么意思?如果事件有关联数据,那么您可以使用不同的委托类型。如果它有多个回调方法,那么它代表多个事件。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-02-06
  • 1970-01-01
  • 2012-11-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-04-25
相关资源
最近更新 更多