4

I wonder if there is a possibility to make the "dynamic" type for variables work for anonymous delegates.

I've tried the following:

dynamic v = delegate() {
};

But then I got the following error message:

Cannot convert anonymous method to type 'dynamic' because it is not a delegate type

Unfortunately, also the following code doesn't work:

Delegate v = delegate() {
};
object v2 = delegate() {
};

What can I do if I want to make a Method that accepts any type of Delegate, even inline declared ones?

For example:

class X{
    public void Y(dynamic d){
    }
    static void Main(){
        Y(delegate(){});
        Y(delegate(string x){});
    }
}
Van Coding
  • 24,244
  • 24
  • 88
  • 132
  • 5
    Any reason not to use `Func<>` or `Action<>`? – Jamiec May 24 '12 at 13:51
  • @Jamiec I suppose because that won't satisfy the criteria of not caring what the signature of the delegate is. That said, it would boil down to calling Invoke with an `object[]` of parameters, which could then be expressed in `Func<>`. – Adam Houldsworth May 24 '12 at 13:53
  • You're not declaring any delegate type there. – user703016 May 24 '12 at 13:54
  • 1
    @AdamHouldsworth - Yep, having re-read the question I get the point now, but it doesnt make much sense. You must have to *do* something with the delegate which means your program must understand the I/O of the delegate. – Jamiec May 24 '12 at 13:56
  • @Jamiec because Func<> and Action<> has a FIX count/type of parameters. It has to be specified every time. I don't want to do this. – Van Coding May 24 '12 at 13:56
  • As an incomplete solution, you could make overloads of Y that accept variations of `Func`, `Func`, `Func`...I know that's not what you're looking for, but it's a start if you can't solve it with an arbitrary delegate signature. – Justin Morgan - On strike May 24 '12 at 13:56
  • @Jamiec It doesn't need to understand the I/O. A delegate boils down to "I can call it and give it something to work with", generically that means a call method (Invoke usually) and general arguments: `object[]`. My answer shows this. – Adam Houldsworth May 24 '12 at 13:57

3 Answers3

5

This works, but it looks a little odd. You can give it any delegate, it will run it and also return a value.

You also need to specify the anonymous method signature at some point in order for the compiler to make any sense of it, hence the need to specify Action<T> or Func<T> or whatever.

Why can't an anonymous method be assigned to var?

    static void Main(string[] args)
    {
        Action d = () => Console.WriteLine("Hi");
        Execute(d); // Prints "Hi"

        Action<string> d2 = (s) => Console.WriteLine(s);
        Execute(d2, "Lo"); // Prints "Lo"

        Func<string, string> d3 = (s) =>
        {
            Console.WriteLine(s);
            return "Done";
        };
        var result = (string)Execute(d3, "Spaghettio"); // Prints "Spaghettio"

        Console.WriteLine(result); // Prints "Done"

        Console.Read();
    }

    static object Execute(Delegate d, params object[] args)
    {
        return d.DynamicInvoke(args);
    }
Community
  • 1
  • 1
Adam Houldsworth
  • 63,413
  • 11
  • 150
  • 187
  • 1
    couldnt you make the second param of `Execute` into `params` making it look less weird? See: http://rextester.com/KMX49960 – Jamiec May 24 '12 at 13:57
  • This is what I already got. The problem here is, that I have to specify the signature of the Action for every delegate I pass to execute. With this question I wanted to find a way to avoid this. – Van Coding May 24 '12 at 13:59
  • @VanCoding I can't think of a way to avoid that, but that said, it won't matter or create any problems. You *know* what the signature is because you are creating the signature in-line, you simply need to cast it to that signature before giving it to the method. – Adam Houldsworth May 24 '12 at 14:00
  • @AdamHouldsworth that's sad, because specifying it seems absolutely unnecessary to me... It makes the whole code very awkward... No developer wants to define the type twice... It's not a matter of knowing the type, its a matter of code design. – Van Coding May 24 '12 at 14:02
  • 1
    @VanCoding It might be the same reason you cannot assign a lambda into a `var`. – Adam Houldsworth May 24 '12 at 14:03
  • @Jamiec Yes true, I have amended my code to look "less weird"... lol – Adam Houldsworth May 24 '12 at 14:04
  • @AdamHouldsworth Isn't there a way to do it like this: `Action x = delegate(string y) {};`? It doesn't work but maybe its another idea... – Van Coding May 24 '12 at 14:15
1

If you declare a type for each of your delegates, it works.

// Declare it somewhere
delegate void DelegateType(string s);

// The cast is required to make the code compile
Test((DelegateType)((string s) => { MessageBox.Show(s); }));

public static void Test(dynamic dynDelegate)
{
    dynDelegate("hello");
}
user703016
  • 37,307
  • 8
  • 87
  • 112
0
Action _;
dynamic test = (_ = () => Console.WriteLine("Test"));
test() // Test