2016-02-13 26 views
5

La mia comprensione delle azioni in C# è che sono solo una versione specifica di un delegato, vale a dire una senza parametri e nessun tipo di ritorno.Perché è legale invocare un'azione senza averla prima assegnata a qualcosa?

Se creo una classe come questa ...

class TrainSignal 
{ 
    public delegate void TrainsAComing(); 

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

... non si compila visto che non ho creato un'istanza del delegato. Tuttavia, se si sostituisce la definizione di delegato con quella di un azione come qui di seguito compila:

class TrainSignal 
{ 
    public Action TrainsAComing; 

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

Ho pensato che forse che forse un'azione è statico o qualcosa del genere (consentendo in tal modo noi chiamiamo con il suo nome, senza istanziare esso) ma non sembra essere il caso.

Qualcuno può spiegare perché il secondo blocco di codice è legale?

risposta

4

Questa linea

public delegate void TrainsAComing(); 

definisce un delegato pubblico tipo chiamato TrainsAComing, nidificato all'interno vostra classe. Ciò consentirebbe agli utenti di creare delegati di tipo TrainSignal.TrainsAComing, ma TrainSignal non avrebbe alcun membro per memorizzare un'istanza di tale delegato.

In altre parole, la dichiarazione del delegato fa non definisce un membro del tipo delegato. Hai bisogno di un'altra dichiarazione per questo:

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

    public TrainsAComing OnTrainsAComing; // The member of delegate type 

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

Action, d'altra parte, è già un tipo, simile a delegate TrainsAComing dal vostro esempio. Quindi, la definizione

public Action TrainsAComing; 

rende TrainsAComing un membro di TrainSignal grado di memorizzare un delegato.

3

Un campo Action è un campo come qualsiasi altro. È un tipo di ref, quindi il campo è null inizializzato. Riceverai un NullReferenceException. Questo è perfettamente sicuro ma non utile.

Forse intendevi effettivamente fare riferimento a una funzione?

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

O forse, la confusione deriva dal fatto che il primo frammento di codice dichiara un tipo di delegato ed il secondo dichiara un campo di un tipo delegato.