private void StringAction(string aString) // method to be called
{
return;
}
private void TestDelegateStatement1() // doesn't work
{
var stringAction = new System.Action(StringAction("a string"));
// Error: "Method expected"
}
private void TestDelegateStatement2() // doesn't work
{
var stringAction = new System.Action(param => StringAction("a string"));
// Error: "System.Argument doesn't take 1 arguments"
stringAction();
}
private void TestDelegateStatement3() // this is ok
{
var stringAction = new System.Action(StringActionCaller);
stringAction();
}
private void StringActionCaller()
{
StringAction("a string");
}
I don't understand why TestDelegateStatement3
works but TestDelegateStatement1
fails. In both cases, Action
is supplied with a method that takes zero parameters. They may call a method that takes a single parameter (aString
), but that should be irrelevant. They don't take a parameter. Is this just not possible to do with lamda expressions, or am I doing something wrong?
As you said, Action doesn't take any parameters.
If you do this:
var stringAction = new System.Action(StringAction("a string"));
You actually execute the method here, so that is not a method parameter.
if you do this:
var stringAction = new System.Action(param => StringAction("a string"));
you tell it that your method takes a parameter called param
, which Action does not.
So the correct way to do this would be:
var stringAction = new System.Action( () => StringAction("a string"));
or more compact:
Action stringAction = () => StringAction("a string");
the empty brackets are used to indicate the lambda doesn't take any parameters.
Action
delegate is defined as delegate to method, that has no parameters and returns void. In sample 1, you are making 2 mistakes:
1. You are trying to give method, that takes parameter
2. You are invoking the method, and not giving it as a parameter (it should be new Action(methodName)), although, it wouldn't work because of 1.
In sample 2, you are making the same mistake again, your lambda is taking a parameter, you should write it like this:
new Action(() => StringAction("a string"));
If you want to create a delegate, that will take a parameter, you should do it like this:
new Action<string>(myStringParam => StringAction(myStringParam));
So, in your case, complete code would look like this:
private void StringAction(string aString) // method to be called
{
return;
}
private void TestDelegateStatement1() // now it works
{
var stringAction = new Action<string>(StringAction);
//You can call it now:
stringAction("my string");
}
private void TestDelegateStatement2() // now it works
{
var stringAction = () => StringAction("a string");
//Or the same, with a param:
var stringActionParam = (param) => StringAction(param);
//You can now call both:
stringAction();
stringActionParam("my string");
}
private void TestDelegateStatement3() // this is ok
{
var stringAction = new System.Action(StringActionCaller);
stringAction();
}
private void StringActionCaller()
{
StringAction("a string");
}
I'm not an expert on this, but have you tried this?
public void TestDelegateStatement4
{
var stringAction = () => StringAction("a string");
}
In C# 2.0, the Action
delegate is a void
delegate that doesn't accept parameters.
In later versions, there's the generic Action<T>
delegate, where T specifies the parameter type.
This should work:
var stringAction = new Action<string>(param => StringAction(param));
or even better:
var stringAction = new Action<string>(StringAction); // using method group conversion
then, you can call
stringAction("Hello world");