25

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.

Tim Schmelter
  • 450,073
  • 74
  • 686
  • 939
bkjvbx
  • 969
  • 1
  • 10
  • 22
  • 13
    Perhaps it's worth illustrating your question with the java code you're trying to port, and your attempt so far? – Rowland Shaw Dec 03 '14 at 13:49
  • Your question is unclear so I won't VTC it yet, but you might want to check out http://stackoverflow.com/questions/191013/can-a-c-sharp-anonymous-class-implement-an-interface – Jeroen Vannevel Dec 03 '14 at 13:50
  • 2
    You could implement the interface in an inner class. That way, you CAN access the private members of the calling class. – Dennis_E Dec 03 '14 at 13:51
  • 1
    It almost sounds like you want a private nested class. – Aron Dec 03 '14 at 13:51
  • Many cases of anonymous types in Java can be replaced by events or lambdas in C#. – Dirk Dec 03 '14 at 14:08
  • you can become a compiler – nicolas May 12 '16 at 09:29
  • It's a pity that .NET does not support anonymous classes. Now, if an overridden class is only used within a single method, a class outside of this method needs to be defined. – kap Dec 08 '19 at 22:02

3 Answers3

20

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() {
}
GvS
  • 52,015
  • 16
  • 101
  • 139
18

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

Andy Turner
  • 137,514
  • 11
  • 162
  • 243
Dan
  • 10,282
  • 2
  • 37
  • 64
  • 1
    "although you most certainly want to try and stick to using publicly accessible members of both types" Why? – weston Dec 03 '14 at 14:04
  • Coupling. Though I suppose in this instance it is moot given it is a private nested class. I would personally try to avoid using private methods from the nested class if I could avoid it - that's not what private is used for. I probably should have mentioned I meant avoid using private methods, rather than avoid using internal/protected, from within the nested class. Also, I would assume that given you are implementing an interface as a nested class, you wouldn't want to touch the private methods of the nested class from the parent. – Dan Dec 03 '14 at 14:07
  • Thanks for your response. As per your example using a nested private class: IMyInterface might need to be implemented in different ways in different classes. So Foo() might need access to the instance of MyClass and parameters passed to Bar() here. But elsewhere, it might need other parameters etc. It sounds like you're correct, and my solution needs major refactoring. Thinking I could keep the same structure as the java implementation was probably foolish :) It does sound like I could use Events. In some cases these events would have to be implemented by those using the SDK, is that possible? – bkjvbx Dec 03 '14 at 15:02
  • If you're referring to the Java SDK, I'm afraid interop is beyond the scope of my abilities. – Dan Dec 03 '14 at 15:06
  • because there's (almost) never a good reason for anonymous classes. @nicolas They're an example of an XY problem. The only acceptable use for an anonymous class is in generated code, and even then a better idea is to use generated class names. The biggest reason why anonymous classes were even used in Java was because there was no lambda type – Dan May 12 '16 at 09:53
  • @DanPantry based on... What ? F# has it and it's better designed than c# it has nothing to do with lambda or whatnot, you just want to implement an interface inline. You are not a compiler. – nicolas May 13 '16 at 20:46
  • @nicolas Based on the fact that it is not often you ever want to implement an interface inline.. F# has structural typing so it makes sense there – Dan May 13 '16 at 20:56
  • @DanPantry i don't see what structural typing has to do here as a user. I have an interface IQuack. I want to write inline an IQuack object, end of the story. Interface is about abstraction, there is no reason to not let people abstract. If you have principles against that, you are missing some concepts – nicolas May 14 '16 at 09:37
  • Couple thoughts on the "smell": 1. Running code from the calling class based on decisions made by the called class is not necessarily heavy coupling. We use patterns such as Decorator, or callbacks to keep these relationships abstracted / decoupled. 2. coupling is neither good nor bad. Code that should pivot together, should be tightly coupled. Code that should not, should be loosely coupled or not coupled. It is only bad when things are tightly coupled but should not be, or are not tightly coupled but should be. – Aaron T Harris Jul 03 '23 at 21:15
2

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

    ...
}
weston
  • 54,145
  • 21
  • 145
  • 203
  • Nested classes can access the instance of the parent class that created them by using `OuterClass.this`. – Samah Oct 26 '17 at 10:19
  • @Samah What do you mean? Are you talking about Java? If so, you are right. But this guy is explaining C#. In C# you can't use `OuterClass.this`. – Jenix Aug 16 '18 at 17:32