Click here to Skip to main content
15,889,116 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hi,

While trying to follow an example, I came across some syntax I have not seen before. I have so far failed to find an explanation for it on the internet.

The line of code is one constructor chaining to another. This is the code:


C#
public class Command
{
    public Command(Action<object> execute)
    {
    }

    public Command(Action execute) : this( (Action<object>) ( o => execute() ) )
    {
    }
}



Can anyone please explain what is going on here?


Kind wishes ~ Patrick
Posted
Updated 8-Jan-16 5:40am
v3
Comments
Mehdi Gholam 7-Jan-16 14:29pm    
I think you may be missing a "class" i.e. public class Command(...
Dave Kreskowiak 7-Jan-16 14:55pm    
No, he's not. This is a constructor.
Sergey Alexandrovich Kryukov 7-Jan-16 16:16pm    
No, this line of code will perfectly compile if surrounded by right context; and this is one of the rare cases when this context is obvious. Please see the solutions.
—SA

This is a class instance constructor for a class called "Command".

The stuff after the colon is just calling another constructor of the same name in the same class, passing in an Action<> object which is defined as a lambda expression.

There should be another Command(Action<>) somewhere else in the class.
 
Share this answer
 
Comments
Sergey Alexandrovich Kryukov 7-Jan-16 16:14pm    
This is not quite clear and not even quite accurate, in part of the other constructor: Command(Action<>).
I tried to clarify it in Solution 2, please see.
—SA
To make the Solution 1 more accurate:

To make the code compile, it should be included in the class definition like this:
C#
using System;

// ...

public class Command {

    // one constructor:
    public Command(Action<object> action) {
        // ...
    }

    // another constructor calls the constructor above:
    public Command(Action execute)
        : this((Action<object>)(o => execute())) {
            // no need in the method body;
            // it's implemented via "this(...)"
    }

    // ...
}

The constructor could not be of the type Command(Action<>); Action<> would not be a complete type. At the same time, the call to the other constructor clearly indicate that the actual generic parameter of the first constructor is Action<System.Object>.

So, let's see what's going on. I hope, first constructor (which you did not show) is clear. It does not matter what its implementation does; but the delegate instance action can be invoked in this constructor, or just preserved to be invoked later, eventually. This delegate instance has a parameters of the type System.Object, which is passed to the delegate instance passed as a parameter to the first constructor. For the declaration of all Action delegates, see the namespace System, assembly "System.Core".

The second constructor accepts the parameters of the type System.Action, which is the void delegate without a parameter. The whole purpose of this constructor call the constructor above (which is done in the part of the construct after ':'), and the trick is to ignore System.Object the parameter of the action, which is represented by the parameter o in the delta expression. The constructor implementation wraps the method ignoring the parameter in this lambda expression.

[EDIT, in response to some follow-up questions below]

In the code sample above, the "type cast" syntax is used, the (complete) type in round brackets, (Action<object>). This is done because of type inference used in lambda expressions. Indeed, the type of the object o is not specified. Even though the parameter is ignored, the implementation needs to know its type. Sometimes, one can infer the type from the fact that there is only one other constructor; this is the inference I have to perform to answer this question. But this is not how the compiler's type inference works; it needs more certain information.

See also: Implicitly Typed Local Variables (C# Programming Guide)[^].

I don't like the syntax shown above and usually use slightly different syntax, with a constructor:
C#
public class Command {

    public Command(Action<object> action) {/* ... */}

    public Command(Action execute)
        : this(new Action<object>(o => execute())) {
    }

    // ...
}


—SA
 
Share this answer
 
v6
Comments
Mehdi Gholam 8-Jan-16 0:41am    
5'ed and happy new year!
Sergey Alexandrovich Kryukov 8-Jan-16 11:25am    
Thank you, Mehdi.
Happy New Year!
—SA
George Swan 8-Jan-16 2:34am    
Have I got this correct? In the Command class,the Action() delegate is invoked by invoking another Action delegate that takes an object as a parameter and calls the Action() delegate but the object is never used? This seems very messy.
Sergey Alexandrovich Kryukov 8-Jan-16 11:59am    
It is not messy at all, just the opposite; writing it all in different way would create more mess. However, I think my syntax is a bit better — please see my update to the my answer, after [EDIT...].

Now, the phrasing is a bit complicated, but this is just such kind of things where phrasing is always much more complicated then actual understanding. The idea is to understand things without trying to phrase it. But if you want to phrase, you need to phrase it correctly. There is no such thing as Action(). There are different types of Action and Action<>, first type is not generic, and other are generic types. You instantiate a type to a complete type by specifying concrete (actual) generic parameters. Then, you need to make difference between delegate types and instances. Then, you cannot call a delegate, you call a delegate instance, more exactly, you invoke it (and the difference is essential, because the instance can be a multicast delegate). I tried to explain it (including the invocation of a separate handler from the invocation list) in my article "Dynamic Method Dispatcher".

—SA
Patrick Skelton 8-Jan-16 4:13am    
Sorry the code was not complete. I was trying (too hard) to be concise. Slapped hands for me.

Thank you for all the replies. I think I understand your answer, Sergey. The part that really confused me was the (Action<object>) where this() chains to the first constructor. Is this a plain cast? I've never seen a cast in this context before.

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900