如何在 C# 中使用匿名类重新实现 Java 侦听器

Posted

技术标签:

【中文标题】如何在 C# 中使用匿名类重新实现 Java 侦听器【英文标题】:How to reimplement Java listeners with anonymous classes in C# 【发布时间】:2014-09-20 15:41:29 【问题描述】:

我正在尝试在 C# 中复制我的 Java 代码,我想知道如何在 C# 中复制此 Java 功能。

Util.java

public class Util

    public void function(String s, final SetAvailabilityStatusListener setStatusListener)
    
        // ....
    

    public static interface SetAvailabilityStatusListener 
        public void setAvailabilityStatus(Status status);
    

Activity.java

public class Activity

    public void anotherFunction()
    
        util.function("name", new SetAvailabilityStatus()
            
                @Override
                public void setAvailabilityStatus(Status status) 
                    loginSetAvailabilityStatus(status);
                
            
           

【问题讨论】:

那究竟是哪个 Java 功能? C# Java-like inline extension of classes?的可能重复 【参考方案1】:

使用委托。它们用于 C# 而不是实现接口的 Java 匿名类。

public class Util

    public void Function(String s, Action<Status> setStatusListener)
    
        // ....
        setStatusListener("myStatus");
    


public class Activity

    private Util util = new Util();
    public void AnotherFunction()
    
        util.Function("name", status => LoginSetAvailabilityStatus(status));
    

    public void LoginSetAvailabilityStatus(string status)
        //do something with status
    



【讨论】:

【参考方案2】:

我找不到合适的副本,所以:

1. C# 没有像 Java 那样的匿名类,但没有人阻止您手动创建所需的侦听器类

public class Util

    public void Function(String s, ISetAvailabilityStatusListener setStatusListener)
    
        // ....
    

    public interface ISetAvailabilityStatusListener 
        public void SetAvailabilityStatus(Status status);
    


public class Activity

    private class MySetAvailabilityStatusListener: Util.ISetAvailabilityStatusListener
    
        public void SetAvailabilityStatus(Status status) 
        
            // do your handling, but nested classes have some differences with anonymous Java classes, so it may require additional infrastructure.
        
    

    public void AnotherFunction()
    
        utilObj.Function("name", 
            new MySetAvailabilityStatusListener())
           

就是所谓的observer design pattern(只是没有注销方法!!)。

2. 正如@AndreySarafanov 已经建议的那样,您可以使用Action Delegates 和lambda expressions:

public class Util

    public void Function(String s, Action<Status> statusChangeListener)
    
        // ....
    


public class Activity

    public void AnotherFunction()
    
        utilObj.Function("name", 
            (status) => 
            
                loginSetAvailabilityStatus(status);
            
           

3. C# 有另一种更简单的机制来处理事件处理(订阅)机制 - events and delegates

public class StatusEventArgs : EventArgs

    //...


public class Util

    public void SomeFunction()
    
        // ....
        if (this.OnAvailabilityChanged != null)
            OnAvailabilityChanged(this, new StatusEventArgs(status));
    

    public event EventHandler<StatusEventArgs> OnAvailabilityChanged


public class Activity

    public void AvailabilityStatusChangedHandler(object sender, EventArgs<Status> eventArgs) 
    
    

    public void AnotherFunction()
    
        utilObj.OnAvailabilityChanged += this.AvailabilityStatusChangedHandler;
           

它不允许你将 name 属性与事件处理程序相关联,你可以通过特殊的注册方法来克服它,但它会降低事件的可用性,所以你应该坚持另一种解决方案。

【讨论】:

我采用了@AndreySarafanov 提供的解决方案,但我相信您分享的信息对我在这个项目中的推进很有用。非常感谢 嗨。经过一番挣扎,我发现您的第三种方法最适合我的用例。但是当我使用App.Current.Resources["ResourceName"] 时,它会给出“无效的跨线程访问。”错误。我实际上是从 AsyncCallback 函数调用它。 public void UserAvailabilityCallback(IAsyncResult ar)。据我所知,这在单独的线程上运行。你能建议一个修复吗?如果我在某处做错了,请纠正我。我正在使用Deployment.Current.Dispatcher 来解决这个问题。可以做其他事情来代替这个吗? @PratPor 这是另一个与此问题没有直接关系的问题,因此您可能应该将其作为一个全新的问题提出 - 这个问题已经达到了它的目标。请阅读***.com/questions/8240490/…,然后再询问以更好地了解可能的问题和解决方案。 我认为第一个选项是一种更有用的方法,因为它可以更好地处理多个接口方法的情况,并且还允许您维护从 Java 到 C# 的接口(委托不能代替接口一般)。 @DaveDoknjas 是的,代表可能有点被嘲笑地称为穷人的观察者模式。它们是 UI 事件处理(在一个 UI 元素内)的有效解决方案,但对于更复杂的事情,您最终会使用更复杂的解决方案。

以上是关于如何在 C# 中使用匿名类重新实现 Java 侦听器的主要内容,如果未能解决你的问题,请参考以下文章

对 Java 的匿名内部类理解

凌空请求的匿名侦听器导致内存泄漏

java中常用APIScanner类匿名对象Random类ArrayList类对象数组

Java 中如何使用匿名内部类?

像我们在 C# linq 中一样在 java 8 中获取匿名对象

Java中匿名内部类