24

I know it can be done in Java, as I have used this technique quite extensively in the past. An example in Java would be shown below. (Additional question. What is this technique called? It's hard to find an example of this without a name.)

public abstract class Example {
   public abstract void doStuff();
}

public class StartHere{
   public static void main(string[] args){
      Example x = new Example(){
         public void doStuff(){
            System.out.println("Did stuff");
         }            
      };
      x.doStuff();
   }
}

Now, my main question would be, can this also be done in C#, and if so, how?

vipirtti
  • 1,058
  • 4
  • 15
  • 24

9 Answers9

21

The Java technique is called "Anonymous inner class", and there is no equivalent in C#.

Anton Gogolev
  • 113,561
  • 39
  • 200
  • 288
17

With lamba expressions and class initializers you can get the same behaviour with a bit of effort.

public class Example {
    public Action DoStuff;
    public Action<int> DoStuffWithParameter;
    public Func<int> DoStuffWithReturnValue;
}

class Program {
    static void Main(string[] args) {
        var x = new Example() {
            DoStuff = () => {
                Console.WriteLine("Did Stuff");
            },
            DoStuffWithParameter = (p) => {
                Console.WriteLine("Did Stuff with parameter " + p);
            },
            DoStuffWithReturnValue = () => { return 99; }


        };

        x.DoStuff();
        x.DoStuffWithParameter(10);
        int value = x.DoStuffWithReturnValue();
        Console.WriteLine("Return value " + value);
        Console.ReadLine();
    }
}

One problem with this solution that I just realized is that if you were to create fields in the Example class, the lambda expressions would not be able to access those fields.

However, there is no reason that you could not pass the instance of Example to the lambda expressions which would give them access to any public state that example might hold. AFAIK that would be functionally equivalent to the Java Anonymous Inner Class.

P.S. If you are going to vote an answer down, do us all a favour and add a comment as to why you disagree :-)

Darrel Miller
  • 139,164
  • 32
  • 194
  • 243
  • 2
    This is **not** the same behaviour. The most useful part about of anonymous inner classes is being able to quickly extend a class without having to define an entire new type. – makhdumi Feb 14 '14 at 19:19
10

Typically, problems that are solved with anonymous inner classes in Java are solved in a much cleaner fashion using delegates in .Net. Your example is a little too simplistic to determine your intent. If your intent by using the abstract class is to pass around a "behavior" think about just using an Action delegate instead.

public class StartHere{
   public static void main(string[] args){
      Action doStuff = () => Console.WriteLine("Did stuff");
      executeSomething(doStuff);
   }

   public static void executeSomething(Action action)
   {
      action();
   }
}
Michael Meadows
  • 27,796
  • 4
  • 47
  • 63
8

That can't be done in C#; you need to declare a new class type. The closest you can get in C# is probably a named nested class:

public class StartHere{
    private class Foo : Example {
        public override void  doStuff()
        {
            Console.WriteLine("did stuff");
        }
    }
   public static void Main(string[] args){
      Example x = new Foo();
      x.doStuff();
   }
}
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • It's worth mentioning that an inner `private class` in C# would match Java's `private static class` inner class, and thus can't access members of the containing class. – Jean-Philippe Pellet Nov 19 '13 at 09:53
  • @Jean-PhilippePellet that's not true; a `private class` in C# *does* have access to *members* of the containing class (even `private` members). What it lacks is an *instance* of the containing class. If an instance is made available to the nested class, the nested class has full access to the members. – Marc Gravell Nov 19 '13 at 10:00
  • OK, thanks for the clarification; I worded my sentence (and used the word “access”) badly! – Jean-Philippe Pellet Nov 19 '13 at 11:14
1

This is not supported in C#, and if it were up to me it shouldn't be so either.

The proliferation of inner classes in java is mainly due to the lack of delegates or lambdas, which C# has. So while this type of functionality currently is "your only hope" in java, you can usually use other mechanisms in C# to achieve the same ends. Java feels like playing the piano with one hand in this regard.

(Admittedly a lot of us have gotten quite good at this one-handed playing; and now it seems like we have to wait at least until java 8 for closures...)

krosenvold
  • 75,535
  • 32
  • 152
  • 208
  • 1
    This is not a solution. Instead of saying it can't be done, use X instead, you should show us how to use X to accomplish the same thing. – edthethird Jun 30 '14 at 19:40
1

While all good answers, most of the work arounds suggested rely on C# 3.0

So, for the sake of completeness, I'll add another solution that uses neither lambdas nor Func type (Granted that, as Matt Olenik mentioned in the comments, one could generalize the below delegates to work the same way.). For those, like me who may still be working with C# 2.0. Maybe not the best solution, but it works.

public class Example
{
    public delegate void DoStuffDelecate();
    public DoStuffDelecate DoStuff;
    public delegate void DoStuffWithDelecate(int n);
    public DoStuffWithDelecate DoStuffWithParameter;
    public delegate int DoStuffWithReturnDelecate();
    public DoStuffWithReturnDelecate DoStuffWithReturnValue;
}

class Program
{
    static int MethodWithReturnValue()
    {
        return 99;
    }
    static void MethodForDelecate()
    {
        Console.WriteLine("Did Stuff");
    }
    static void MethodForDelecate(int n)
    {
        Console.WriteLine("Did Stuff with parameter " + n);
    }


    static void Main(string[] args)
    {
        var x = new Example();
        x.DoStuff = MethodForDelecate;
        x.DoStuffWithParameter = MethodForDelecate;
        x.DoStuffWithReturnValue = MethodWithReturnValue;

        x.DoStuff();
        x.DoStuffWithParameter(10);
        int value = x.DoStuffWithReturnValue();
        Console.WriteLine("Return value " + value);
        Console.ReadLine();
    }
}
vipirtti
  • 1,058
  • 4
  • 15
  • 24
  • -1 for incorrect information about lambda expressions. They do not require .NET 3.5, only C# 3.0. The C# 3.0 compiler can target .NET 2.0. Lambda expressions are only syntactic sugar for delegates. And although the Func type doesn't exist outside System.Core, you can easily define an equivalent. – Matthew Olenik Apr 03 '09 at 02:53
  • Right. I hope this is more accurate. I'm working on a ASP.NET project myself, and I have not found a way to seperately define the Framework used and the C# compiler used, so the previous answer was all I could conjure up with my own eviroment and offical documentation. – vipirtti Apr 03 '09 at 05:40
1

Since your class represents only an action, you can use a delegate in your case, there is an existing delegate :

public delegate void Action();

This is the exact equivalent of your class.

And the déclaration of your anonymous class is even cleaner :

Action action = () => Console.WriteLine("Hello world");
action(); // invoke

you can even use closure :

public void Hello(string name)
{
  Action action = () => Console.WriteLine("Hello " + name);
  action(); // will call the above lambda !
}
thinkbeforecoding
  • 6,668
  • 1
  • 29
  • 31
0

In short no, you have to define it as separate sub class. I think this feature is coming C# 4.0 though?

Edit: No it's not coming C# 4.0 I made that up.

Chris S
  • 64,770
  • 52
  • 221
  • 239
0

You are able to accomplish this with Mocking in .NET. However there is no in-language support for this feature, I think it will be available in C# 4.0. There are a number of libraries out there for Mocking, including:

Nick Berardi
  • 54,393
  • 15
  • 113
  • 135