3
votes

I have taken a look at this Question diference between delegate and action

and I'm still wondering why can I pass lambda expressions to methods that accept Action type parameters
whereas I can not pass lambda expressions to methods that accept Delegate type parameters
I have this Print method, I'm going to refer to it using action and Delegate

public static void Print()
{
    Console.WriteLine("Printing ..");
}

I created these two methods which will invoke Print method as you can see the first one has Action type parameter and the second one has Delegate type Parameter these parameterss will refer to the method "Print"

public static void ActionParamMethod(Action DAction)
{
    DAction();
}
public static void DelegateParamMethod(Delegate SomeDelegate)
{

}

I'm going to pass lambda expressions to these methods

public static void SomeHowMethod()
{
    DelegateParamMethod(() => Print());
    ActionParamMethod(() => Print());
}

when I try to pass lambda expression to the method which accept Delegate parameter I get this error

Cannot convert lambda expression to type 'System.Delegate' because it is not a delegate type

why it's not delegate type and Action is delegate type ?
why I can pass lambda expressions to methods that accept Action parameters, but I can't pass lambda expressions to methods that accept Delegate parameters?

4

4 Answers

8
votes

Lambdas need to infer the actual type of the delegate used based on context. When attempting to use a lambda in a context where a Delegate is expected the lambda's inference algorithm cannot determine which specific type of delegate it should be. It would be like trying to construct an instance of an interface; you wouldn't know which implementation to choose.

6
votes

The reason is that lambda expressions do not have a type in C# unless you cast them to a concrete type.

Delegate type is the base class for all delegates.It's an abstract class. Unless you specify an actual delegate type like Action or Func, you can't pass a lambda expression as Delegate. It's like you can't instantiate an abstract class but you can pass a class that implements it as a parameter. If you cast your lambda to any delegate type it will work as expected:

DelegateParamMethod((Action<string>)(x => Console.WriteLine(x));

The reason why your first method works without specifying type is because the expression can be converted to Action, otherwise it wouldn't be valid for the same reason why this expression is not valid:

var x = () => Print("Hello world");
1
votes

The problem is that you aren't providing the type of delegate you want to invoke. You are looking for something like:

DelegateParamMethod((Action)(() => Print()));
0
votes

You should not refer to Delegate in your code, it is the base class for delegates but is not meant to be used like you are doing here.

Instead you should choose a delegate type (like your Action example) and use it as the parameter.