Pregunta

No estoy seguro de qué es exactamente lo que está sucediendo aquí, pero parece que en .NET 1.1 un delegado de eventos sin inicializar puede ejecutarse sin problemas, pero en .NET 2.0+ causa una NullReferenceException. Cualquier idea de por qué. El siguiente código se ejecutará bien sin problemas en 1.1, en 2.0 da una NullReferenceException. Tengo curiosidad por qué se comporta de manera diferente? ¿Qué ha cambiado?

Gracias

por ejemplo

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());
    }
}
¿Fue útil?

Solución

[actualizado] AFAIK, no hubo ningún cambio aquí en el manejo fundamental del delegado; la diferencia está en cómo se comporta DataTable.

Sin embargo! Tenga mucho cuidado al usar eventos estáticos, especialmente si se suscribe desde instancias (en lugar de métodos estáticos). Esta es una buena manera de mantener vivas grandes franjas de objetos y no ser recolectados por la basura.

Ejecutar el código a través de csc desde 1.1 muestra que el lado del delegado general es el mismo. Creo que la diferencia es que el código DataTable que genera RowChanged se estaba tragando la excepción. Por ejemplo, haga el código como abajo:

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

Verás " Antes " ;, pero no " Después " ;; el DataTable lanzó una excepción y la tragó.

Otros consejos

El sistema Eventhandler es básicamente una lista de funciones a las que llamar cuando se genera un evento determinado.

Se inicializa en " null " lista, y no la lista vacía, por lo que debe hacer

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

La forma en que funcionan los eventos no ha cambiado realmente de 1.1 a 2

Aunque la sintaxis parece una agregación normal, en realidad no lo es:

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

Desencadenará TableEventHandler y luego al delegado, el nulo se saltará.

Puede usar null para borrar eventos, pero solo dentro de la clase de activación de eventos:

this.MyEvent = null;

Si nada se suscribe, su evento será nulo, vea la respuesta de soraz. La clase DataTable contendrá una comprobación similar y no activará el evento si no hay suscriptores.

El patrón estándar es:

//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(...) );
}
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top