简体   繁体   English

等效于 C# 中的 Java 匿名类?

[英]Equivalent of Java's anonymous class in C#?

I am trying to port an SDK written in java to C#.我正在尝试将用 Java 编写的 SDK 移植到 C#。

In this software there are many "handler" interfaces with several methods (for example: attemptSomethingHandler with success() and several different failure methods).在这个软件中,有许多“处理程序”接口,有几种方法(例如: attemptSomethingHandlersuccess()和几种不同的失败方法)。 This interface is then implemented and instantiated anonymously within the calling class and passed to the attemptSomething method of the SomethingModel class.然后在调用类中匿名实现和实例化该接口,并传递给SomethingModel类的attemptSomething方法。 This is an async method and has several places where it could fail or calls another method (passing on the handler).这是一个异步方法,有几个地方可能会失败或调用另一个方法(传递处理程序)。 This way, the anonymous implementation of attemptSomethingHandler can reference private methods in the class that calls attemptSomething .这样, attemptSomethingHandler的匿名实现就可以引用调用attemptSomething的类中的私有方法。

In C# it is not possible to anonymously implement an interface.在 C# 中,不可能匿名实现接口。 I could explicitly implement a new class, but this implementation would be unique to this calling class and not used for anything else.我可以显式地实现一个新类,但是这个实现对于这个调用类来说是唯一的,不用于其他任何东西。 More importantly, I would not be able to access the private methods in the calling class, which I need and do not want to make public.更重要的是,我将无法访问调用类中的私有方法,而我需要且不想公开这些方法。

Basically, I need to run different code from the calling class depending on what happens in the SomethingModel class methods.基本上,我需要根据SomethingModel类方法中发生的情况从调用类运行不同的代码。

I've been reading up on delegates but this would require passing as many delegates as there are methods in the handler interface (as far as I can tell).我一直在阅读委托,但这需要传递与处理程序接口中的方法一样多的委托(据我所知)。 What is the appropriate way to do this in C#?在 C# 中执行此操作的适当方法是什么? I feel like I'm missing out on a very common programming strategy.我觉得我错过了一个非常常见的编程策略。 There simply must be an easy, clean way to structure and solve this problem.必须有一种简单、干净的方法来构建和解决这个问题。

Using delegates:使用委托:

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

 // Call it using:

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

Or, using a class或者,使用类

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

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

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

Or events或活动

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

In C#, we don't have anonymous types like Java per se.在 C# 中,我们没有像 Java 本身那样的匿名类型。 You can create an anonymous type which contains fields like so:您可以创建一个包含如下字段的匿名类型:

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

However these cannot have methods placed in them and are only passable into methods by use of object or dynamic (as they have no type at compile-time, they are generated by the compiler AFAIK)然而,这些不能在其中放置方法,只能通过使用objectdynamic传递给方法(因为它们在编译时没有类型,它们由编译器 AFAIK 生成)

Instead in C# we use, as you said, delegates or lambdas.正如您所说,在 C# 中,我们使用委托或 lambdas。

If I understand your pickle correctly, you could implement a nested private class like so:如果我正确理解你的泡菜,你可以实现一个嵌套的私有类,如下所示:

interface IMyInterface
{
    void Foo();
}

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

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

Now MyClass can create an instance of MyInterface which implements IMyInterface .现在MyClass可以创建一个实例MyInterface ,它实现IMyInterface As commentors have mentioned, MyInterface can access members of MyClass (although you most certainly want to try and stick to using publicly accessible members of both types).正如评论者所提到的, MyInterface可以访问MyClass成员(尽管您肯定想尝试并坚持使用这两种类型的可公开访问的成员)。

This encapsulates the "anonymous" class (using Java terms here to make it simpler) and also means that you could potentially return MyInterface as an IMyInterface and the rest of the software would be none the wiser.这种封装的“匿名”类(使用Java术语在这里,使其更简单),也意味着你可能会返回MyInterface作为IMyInterface和软件的其余部分将是毫无收获。 This is actually how some abstract factory patterns work.这实际上是一些抽象工厂模式的工作方式。


Basically, I need to run different code from the calling class depending on what happens in the SomethingModel class methods.基本上,我需要根据SomethingModel 类方法中发生的情况从调用类运行不同的代码。

This smells of heavy coupling.这闻起来有重耦合的味道。 Oh dear!哦亲爱的!

It sounds to me like your particular problem could use refactoring.在我看来,您的特定问题可以使用重构。 In C# you can use Events to solve this (note: Can, not should).在 C# 中,您可以使用事件来解决这个问题(注意:可以,不应该)。 Just have an Event for each "branch" point of your method.只需为您的方法的每个“分支”点设置一个事件。 However I must say that this does make your solution harder to envisage and maintain.但是我必须说,这确实使您的解决方案更难设想和维护。

However I suggest you architect your solution in a way such that you don't need such heavy coupling like that.但是,我建议您以一种不需要如此繁重的耦合的方式构建您的解决方案。

You could also try using a Pipeline model but I'm not sure how to implement that myself.您也可以尝试使用管道模型,但我不确定如何自己实现。 I know that jetty (or is it Netty? the NIO for Java by JBOSS) certainly used a similar model.我知道码头(或者是 Netty?JBOSS 的 Java 版 NIO)肯定使用了类似的模型。

You may find that throwing out some unit tests in order to test the expected functionality of your class will make it easier to architect your solution (TDD).您可能会发现,为了测试类的预期功能而放弃一些单元测试将使构建解决方案 (TDD) 变得更加容易。

You can use nested classes to simulate anonymous classes, but in order to use nested classes in the same way as Java you will need to pass a reference to the outer class.您可以使用嵌套类来模拟匿名类,但为了以与 Java 相同的方式使用嵌套类,您需要传递对外部类的引用。 In Java all nested and anonymous classes have this by default, and only static ones do not.在 Java 中,默认情况下所有嵌套和匿名类都有这个,只有静态类没有。

interface IMyInterface
{
    void Foo();
}

class MyClass
{
    public void Bar()
    {
        IMyInterface obj = new AnonymousAnalog(this);
        obj.Foo();
    }

    private class AnonymousAnalog : IMyInterface
    {
        public void Foo(MyClass outerThis)
        {
            outerThis.privateFieldOnOuter;
            outerThis.PrivateMethodOnOuter();
        }
    }

    ...
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM