Question

Je ne sais pas ce qui se passe exactement ici, mais cela donne l'impression que dans .NET 1.1, un délégué d'événement non initialisé peut s'exécuter sans problème, mais dans .NET 2.0+, il provoque une exception NullReferenceException. Des idées pourquoi. Le code ci-dessous fonctionnera correctement sans problème dans la version 1.1; en 2.0, il donne une exception NullReferenceException. Je suis curieux de savoir pourquoi cela se comporte différemment. Qu'est-ce qui a changé?

Merci

par exemple

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());
    }
}
Était-ce utile?

La solution

[mise à jour] autant que je sache, il n'y a pas eu de changement en ce qui concerne le traitement fondamental des délégués; la différence réside dans le comportement de DataTable.

Cependant! Soyez très prudent lorsque vous utilisez des événements statiques, en particulier si vous vous abonnez d'instances (plutôt que de méthodes statiques). C’est un bon moyen de garder d’énormes quantités d’objets en vie et de ne pas être ramassé.

L'exécution du code via csc à partir de 1.1 montre que le côté délégué général est identique. Je pense que la différence est que le code DataTable qui soulève RowChanged avalait l'exception. Par exemple, créez le code comme ci-dessous:

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

Vous verrez "Avant", mais pas "Après"; une exception a été levée et avalée par le DataTable.

Autres conseils

Le système eventhandler est essentiellement une liste de fonctions à appeler lorsqu'un événement donné est déclenché.

Il s’initialise sur le " null " liste, et non la liste vide, vous devez donc faire

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

Le mode de fonctionnement des événements n'a pas vraiment changé de 1.1 à 2

Bien que la syntaxe ressemble à une agrégation normale, elle ne l'est vraiment pas:

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

Lance TableEventHandler puis le délégué - la valeur null est simplement ignorée.

Vous pouvez utiliser la valeur null pour supprimer les événements, mais uniquement dans la classe de déclenchement des événements:

this.MyEvent = null;

Si rien ne s'abonne, votre événement sera nul - voir la réponse de soraz. La classe DataTable contiendra une vérification similaire et ne déclenchera pas l'événement s'il n'y a aucun abonné.

Le modèle standard est:

//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(...) );
}
Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top