Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why is it legal to invoke an Action without have first assigned it to anything?

Tags:

c#

delegates

My understanding of Actions in C# is that they are just a specific version of a delegate, namely one with no parameters and no return type.

If I create a class like this...

class TrainSignal
{
    public delegate void TrainsAComing();

    public void HerComesATrain()
    {
        TrainsAComing();
    }
}

...it won't compile since I haven't created an instance of the delegate. However if I replace the delegate definition with that of an Action like below it compiles:

class TrainSignal
{
    public Action TrainsAComing;

    public void HerComesATrain()
    {
        TrainsAComing();
    }
}

I thought perhaps that maybe an Action is static or something like that (thereby allowing us to call it by it's name without instantiating it) but that doesn't seem to be the case.

Can anyone explain why the second code block is legal?

like image 230
Sperick Avatar asked Feb 13 '16 12:02

Sperick


2 Answers

This line

public delegate void TrainsAComing();

defines a public delegate type called TrainsAComing, nested inside your class. This would let users create delegates of type TrainSignal.TrainsAComing, but TrainSignal would have no member to store an instance of such delegate.

In other words, declaration of the delegate does not define a member of delegate type. You need another declaration for that:

class TrainSignal
{
    public delegate void TrainsAComing(); // The delegate type

    public TrainsAComing OnTrainsAComing; // The member of delegate type

    public void HerComesATrain()
    {
        OnTrainsAComing();
    }
}

Action, on the other hand, is already a type, similar to delegate TrainsAComing from your example. Hence, the definition

public Action TrainsAComing;

makes TrainsAComing a member of TrainSignal capable of storing a delegate.

like image 149
Sergey Kalinichenko Avatar answered Nov 15 '22 23:11

Sergey Kalinichenko


An Action field is a field like any other. It's a ref type, so the field is null initialized. You will receive a NullReferenceException. This is perfectly safe but not useful.

Maybe you meant to actually reference a function?

Action TrainsAComing = () => Console.WriteLine("...");

Or maybe, the confusion comes from the fact that the first code snippet declares a delegate type and the second one declares a field of a delegate type.

like image 3
usr Avatar answered Nov 16 '22 01:11

usr