views:

3510

answers:

9

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?

+9  A: 

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

Anton Gogolev
+5  A: 

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
A: 

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
I'm not aware of anything in C# 4.0 with those characteristics.
Marc Gravell
It was the dynamic keyword I was thinking of
Chris S
Darn... you had me excited there... I searched high-and-low for any official "inner class c# 4.0" references, but none to be had ;-( Plenty of people want it though...
Marc Gravell
A: 

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
+2  A: 

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
+4  A: 

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
+8  A: 

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
A: 

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();
    }
}
DJ Pirtu
-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.
Matt Olenik
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.
DJ Pirtu
A: 

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 !
}
Think Before Coding