相当于Java在C#中的匿名类?

2022-09-01 18:58:46

我正在尝试将用java编写的SDK移植到C#。

在这个软件中,有许多具有几种方法的“处理程序”接口(例如:使用和几种不同的故障方法)。然后,在调用类中匿名实现和实例化此接口,并将其传递给该类的方法。这是一个异步方法,并且有几个地方可能会失败或调用另一个方法(传递处理程序)。这样,匿名实现 可以引用调用 的类中的私有方法。attemptSomethingHandlersuccess()attemptSomethingSomethingModelattemptSomethingHandlerattemptSomething

在 C# 中,无法匿名实现接口。我可以显式实现一个新类,但此实现对于此调用类是唯一的,并且不用于其他任何用途。更重要的是,我无法访问调用类中的私有方法,我需要并且不想公开这些方法。

基本上,我需要根据类方法中发生的情况运行与调用类不同的代码。SomethingModel

我一直在阅读委托,但这需要传递处理程序接口中有多少个方法的委托(据我所知)。在 C# 中执行此操作的适当方法是什么?我觉得我错过了一个非常常见的编程策略。必须有一种简单,干净的方法来构建和解决这个问题。


答案 1

使用委托:

 void AttemptSomethingAsync(Action onSuccess, Action<string> onError1, Action onError2 = null) {
     // ...
 }

 // Call it using:

 AttemptSomethingAsync(onSuccess: () => { Yes(); }, onError1: (msg) => { OhNo(msg); });

或者,使用类

 class AttemptSomethingHandler {
     Action OnSuccess;
     Action<string> OnError1;
     Action OnError2;
 }

 void AttemptSomethingAsync(AttemptSomethingHandler handler) {
     // ...
 }

 // And you call it like
 AttemptSomethingAsync(new AttemptSomethingHandler() {
       OnSuccess = () => { Yes() };
 }); 

或事件

public delegate void SuccessHandler();
public delegate void ErrorHandler(string msg);

class SomethingModel {
     public event SuccessHandler OnSuccess;
     public event ErrorHandler OnError1;

     public void AttemptSomethingAsync() {
         // ...
     }
}

// Use it like

var model = new SomethingModel();
model.OnSuccess += Yes;
model.AttemptSomethingAsync();

private void Yes() {
}

答案 2

在C#中,我们没有像Java本身这样的匿名类型。您可以创建一个匿名类型,其中包含如下字段:

var myObject = new { Foo = "foo", Bar = 1, Quz = 4.2f }

但是,这些方法不能在其中放置,并且只能通过使用或(因为它们在编译时没有类型,因此它们由编译器AFAIK生成)传递到方法中。objectdynamic

相反,在 C# 中,正如你所说,我们使用委托或 lambda。

如果我正确地理解了你的泡菜,你可以实现一个嵌套的私有类,如下所示:

interface IMyInterface
{
    void Foo();
}

class MyClass
{
    public void Bar()
    {
        var obj = new MyInterface();
        obj.Foo();
    }

    private class MyInterface : IMyInterface
    {
        public void Foo()
        {
            // stuff
        }
    }
}

现在可以创建一个实例,其实现 .正如评论者所提到的,可以访问的成员(尽管您肯定希望尝试并坚持使用这两种类型的可公开访问的成员)。MyClassMyInterfaceIMyInterfaceMyInterfaceMyClass

这封装了“匿名”类(此处使用Java术语使其更简单),并且还意味着您可以作为一个返回,而软件的其余部分将更加明智。这实际上是一些抽象工厂模式的工作方式。MyInterfaceIMyInterface


基本上,我需要根据 SomethingModel 类方法中发生的情况运行与调用类不同的代码。

这闻起来像是重耦合。哦,亲爱的!

在我看来,你的特定问题可以使用重构。在 C# 中,可以使用 Events 来解决此问题(注意:可以,不应该)。只需为方法的每个“分支”点设置一个事件。但是,我必须说,这确实使您的解决方案更难设想和维护。

但是,我建议您以这样的方式构建解决方案,这样您就不需要像这样繁重的耦合。

您也可以尝试使用管道模型,但我不确定如何自己实现它。我知道jetty(或者是Netty?JBOSS的Java的NIO)肯定使用了类似的模型。

您可能会发现,为了测试类的预期功能而抛出一些单元测试,将更容易构建解决方案 (TDD)。


推荐