2017-03-07 1 views
2

J'ai observé plusieurs procédures Assign() et j'ai remarqué que les événements sont généralement ignorés pendant l'affectation. Par exemple, la méthode d'affectation TBitmap ne copie pas l'événement OnChange. Je veux savoirDelphi - Pourquoi les événements ne sont pas copiés dans les procédures Assign()?

  1. Si c'est une façon communément acceptée pour ne pas copier les événements pendant l'affectation, à savoir si tous les utilisateurs comptent sur le fait que les événements ne sont jamais - et ne doivent jamais être - copiés pendant un rendez-vous?
  2. Pourquoi les événements sont (au moins communément) pas copiés lors d'une assignation?
  3. Ou peut-être que je me trompe, et les événements peuvent parfaitement être copiés, juste en fonction des circonstances?

Cordialement

+1

Il appartient à l'auteur du composant de prendre cette décision. J'imagine que les événements ne sont généralement pas copiés dans le cadre de 'Assign' parce qu'ils sont perçus comme définissant le comportement plutôt que l'état, d'une manière très lâche. Je suppose que l'autre motivation est qu'un événement contient implicitement une référence à un autre objet. 'Assign' devrait copier des valeurs plutôt que des références. Ce serait très troublant si vous écriviez: 'A.Assign (B); B.Free', et gauche 'A' avec un tas de références périmées aux gestionnaires d'événements mis en œuvre par' B'. –

+1

@DavidHeffernan Vraisemblablement, les références de méthode contenues dans les gestionnaires d'événements de B ne lui appartiennent pas ... cela irait plutôt à l'encontre du but, non? Seront-ils généralement des références à des méthodes appartenant à des objets externes qui ont configuré B? –

+2

Ce serait souvent le cas. Peut-être que mon exemple de code était trop simpliste. Mais il y a un danger très clair de références périmées. –

Répondre

5

Je ne suis pas au courant d'une « règle » qui dicte, mais je pense que vous avez raison et il arrive presque jamais. Cela dépend cependant de l'auteur du composant, car Assign est introduit dans TPersistent, mais ne fait rien par lui-même tant que vous n'avez pas implémenté un override. En fait, il lance une exception (X ne peut pas être affecté à Y) par défaut.

Et c'est aussi la puissance d'Assign. La source à partir de laquelle vous attribuez ne doit même pas être le même type de composant, car chaque affectation est une implémentation personnalisée. Dans votre exemple TBitmap, vous pouvez l'assigner à un TPicture, et vous pouvez même assigner d'autres types de graphiques à TBitmap qui permettraient à ces graphismes de se dessiner eux-mêmes sur le canevas du bitmap.

Dans la plupart des cas, sinon tous, que j'ai rencontrés, Assign est à ce sujet: une affectation et parfois même la conversion de données (d'état, si vous voulez) d'un objet dans un autre.

Les événements sont différents. Ce n'est pas à un objet d'avoir un gestionnaire d'événements et de le gérer. Ce n'est pas le travail de cet objet de prendre la décision que ses abonnés veulent également s'abonner à l'autre objet. La valeur de/pointer vers le gestionnaire d'événements ne fait pas partie des données (pertinentes) de l'objet. Il expose simplement la possibilité pour les autres d'écouter les choses qui lui sont arrivées, et si ces choses veulent aussi écouter l'autre objet, ils doivent aussi assigner un gestionnaire d'événement à ces objets. Donc, pour moi, il est parfaitement logique que les événements ne soient pas copiés, et je pense que je n'ai jamais inclus d'événements dans les implémentations Assign que j'ai écrites moi-même.