Domanda

Non sono sicuro di cosa stia succedendo esattamente qui, ma sembra che in .NET 1.1 un delegato di eventi non inizializzato possa essere eseguito senza problemi, ma in .NET 2.0+ provoca una NullReferenceException. Qualche idea sul perché. Il codice seguente funzionerà senza problemi in 1.1, in 2.0 fornisce una NullReferenceException. Sono curioso perché si comporta diversamente? Che cosa è cambiato?

Grazie

es

class Class1
    {
    public delegate void ChartJoinedRowAddedHandler(object sender);



    public static event ChartJoinedRowAddedHandler ChartJoinedRowAdded;
    public static DataTable dt;

    public static void Main()
    {           
        dt = new DataTable();
        dt.RowChanged += new DataRowChangeEventHandler(TableEventHandler);

        object [] obj = new object[]{1,2};
        dt.Columns.Add("Name");
        dt.Columns.Add("Last");
        dt.NewRow();
        dt.Rows.Add(obj);
    }

    private static void TableEventHandler(object sender, DataRowChangeEventArgs e)
    {
        ChartJoinedRowAdded(new object());
    }
}
È stato utile?

Soluzione

[aggiornato] AFAIK, non ci sono state modifiche alla gestione dei delegati fondamentali; la differenza sta nel comportamento di DataTable.

Tuttavia! Fai molta attenzione usando gli eventi statici, specialmente se ti iscrivi alle istanze (piuttosto che ai metodi statici). Questo è un buon modo per mantenere in vita enormi parti di oggetti e non essere spazzati via.

L'esecuzione del codice tramite csc da 1.1 mostra che il lato del delegato generale è lo stesso - penso che la differenza sia che il codice DataTable che genera RowChanged ha ingoiato l'eccezione. Ad esempio, crea il codice come di seguito:

    Console.WriteLine("Before");
    ChartJoinedRowAdded(new object());
    Console.WriteLine("After");

Vedrai " Prima " ;, ma no " Dopo " ;; è stata generata un'eccezione e inghiottita dalla DataTable.

Altri suggerimenti

Il sistema eventhandler è fondamentalmente solo un elenco di funzioni da chiamare quando viene generato un determinato evento.

Si inizializza su " null " elenco e non l'elenco vuoto, quindi è necessario eseguire

if (ChartJoinedRowAdded != null)
      ChartJoinedRowAdded(new object())

Il modo in cui funzionano gli eventi non è cambiato da 1.1 a 2

Anche se la sintassi sembra una normale aggregazione, in realtà non lo è:

dt.RowChanged += TableEventHandler;
dt.RowChanged += null;
dt.RowChanged += delegate (object sender, DataRowChangeEventArgs e) {
    //anon
};

Verrà attivato TableEventHandler e quindi il delegato: il null viene semplicemente ignorato.

È possibile utilizzare null per cancellare gli eventi, ma solo all'interno della classe di attivazione degli eventi:

this.MyEvent = null;

Se nulla si iscrive, il tuo evento sarà nullo - vedi la risposta di soraz. La classe DataTable conterrà un controllo simile e non genererà l'evento se non ci sono abbonati.

Il modello standard è:

//events should just about always use this pattern: object, args
public static event EventHandler<MyEventArgs> ChartJoinedRowAdded;


//inheriting classes can override this event behaviour
protected virtual OnChartJoinedRowAdded() {
    if( ChartJoinedRowAdded != null )
        ChartJoinedRowAdded( this, new MyEventArgs(...) );
}
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top