Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Equivalent of Java's anonymous class in C#?

Tags:

java

c#

I am trying to port an SDK written in java to C#.

In this software there are many "handler" interfaces with several methods (for example: attemptSomethingHandler with success() and several different failure methods). This interface is then implemented and instantiated anonymously within the calling class and passed to the attemptSomething method of the SomethingModel class. 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.

In C# it is not possible to anonymously implement an interface. 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.

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#? 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.

like image 214
bkjvbx Avatar asked Dec 03 '14 13:12

bkjvbx


3 Answers

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() {
}
like image 59
GvS Avatar answered Oct 11 '22 06:10

GvS


In C#, we don't have anonymous types like Java per se. 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)

Instead in C# we use, as you said, delegates or 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. 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).

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. 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.

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). 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.

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).

like image 45
Dan Avatar answered Oct 11 '22 04:10

Dan


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. In Java all nested and anonymous classes have this by default, and only static ones do not.

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

    ...
}
like image 2
weston Avatar answered Oct 11 '22 05:10

weston