28 votes

La différence entre un destructeur et un finisseur ?

Remarque : Cette question concerne la différence de terminologie entre les mots "destructeur" et "finalisateur" et leur utilisation correcte. J'ai simplement fourni des exemples de leur utilisation en C# et C++/CLI pour démontrer pourquoi je pose la question. Je suis parfaitement conscient de la manière dont ils sont mis en œuvre dans le C# et le CLR, mais je pose la question de l'utilisation correcte de la terminologie.


Dans le monde du C#, les termes "destructeur" et "finalisateur" semblent être utilisés de manière interchangeable, ce qui, je pense, est dû au fait que la spécification du C# décrit la fonctionnalité de nettoyage non déterministe en utilisant le mot "destructeur", alors que la documentation du CLR utilise toujours le mot "finalisateur", de sorte que dans le cadre du C#, ils ont la même signification.

Cependant, la spécification C++/CLI fait une distinction entre les deux. Elle autorise le nettoyage déterministe et non déterministe, et utilise le terme "destructeur" pour la fonctionnalité déterministe et "finalisateur" pour la fonctionnalité non déterministe :

Le finisseur fournit un nettoyage non déterministe. Un finaliseur est une fonction de la "dernière chance" qui est exécutée pendant la collecte des déchets, généralement sur un objet dont le destructeur n'a pas été exécuté.

En outre, les descriptions Wikipedia de destructeur y finaliseur indique que les destructeurs et les finaliseurs sont des concepts distincts, et soutient l'utilisation des termes par la spécification C++/CLI en ce qui concerne le déterminisme :

Contrairement aux destructeurs, les finaliseurs ne sont pas déterministes. Un destructeur est exécuté lorsque le programme libère explicitement un objet. Un finaliseur, en revanche, est exécuté lorsque le système interne de ramassage des ordures libère l'objet.

Les questions :

  • Existe-t-il, d'un point de vue informatique, une différence clairement définie entre un "destructeur" et un "finalisateur", ou la terminologie ne peut-elle être définie que de manière contextuelle ?

  • S'il existe une différence clairement définie, pourquoi la spécification C# utilise-t-elle la "mauvaise" terminologie ?

34voto

Eric Lippert Points 300275

1) Existe-t-il une différence bien définie entre les termes "destructeur" et "finalisateur" tels qu'ils sont utilisés dans l'industrie ou le monde universitaire ?

Il semble bien que ce soit le cas. La différence semble être que les destructeurs sont des méthodes de nettoyage qui sont invoquées de manière déterministe, alors que les finaliseurs s'exécutent lorsque le ramasseur d'ordures leur demande de le faire.

2) Dans ce cas, la spécification C# se trompe -- les finaliseurs sont appelés "destructors" en C#. Pourquoi les auteurs de la spécification C# se sont-ils trompés ?

Je ne sais pas, mais je peux deviner. En fait, j'ai deux suppositions.

L'hypothèse n°1 est que le 12 mai 1999, il n'y avait pas d'article wikipedia décrivant clairement la différence subtile entre ces deux concepts. C'est parce qu'il n'y avait pas de wikipédia. Tu te souviens de l'époque où il n'y avait pas de wikipédia ? L'âge des ténèbres, mec. L'erreur pourrait simplement avoir été une erreur honnête, en croyant que les deux termes étaient identiques.

Heck, pour ce que j'en sais, les deux termes étaient identique le 12 mai 1999, et la différence entre les définitions n'a évolué que plus tard, lorsqu'il est devenu évident qu'il était nécessaire de faire la distinction entre les méthodes de nettoyage rapide et les méthodes de nettoyage paresseux.

La deuxième hypothèse est que le 12 mai 1999, le comité de conception du langage a souhaité laisser ouverte la possibilité qu'un "destructeur" puisse être implémenté sous la forme suivante autre qu'un finisseur. En d'autres termes, le "destructeur" a été conçu comme un concept du langage C# qui ne correspondait pas nécessairement au concept de "finalisateur" de .NET. Lorsque l'on conçoit un langage en même temps que l'on conçoit le cadre sur lequel il repose, on veut parfois se prémunir contre des changements de conception tardifs dans ses sous-systèmes.

Les notes du comité linguistique pour le 12 mai 1999 se lisent comme suit :

Nous allons utiliser le terme "destructeur" pour le membre qui s'exécute lorsqu'une instance est récupérée. Classes peuvent avoir des destructeurs ; les structs ne le peuvent pas. Contrairement au C++, un destructeur ne peut pas être être appelé explicitement. La destruction est non-déterministe - on ne peut pas savoir de manière savoir quand le destructeur s'exécutera, sauf pour dire qu'il s'exécute à un moment après que toutes les références à l'objet l'objet ont été libérées. Le site destructeurs dans une chaîne d'héritage sont appelés dans l'ordre, du plus descendant au moins descendant. Le site n'est pas nécessaire (et pas possible) que le programme classe dérivée d'appeler explicitement le destructeur de base. Le compilateur C# compile les destructeurs dans la classe représentation CLR appropriée. Pour cette version, cela signifie probablement un finaliseur d'instance qui est distingué dans les métadonnées. CLR peut fournir des finaliseurs statiques dans le dans le futur ; nous ne voyons pas d'obstacle à ce que C# utilise des finaliseurs statiques.

Voilà, vous savez maintenant tout ce que je sais sur le sujet. Si vous voulez en savoir plus, demandez à Anders la prochaine fois que vous le verrez.

7voto

philsquared Points 13547

Strictement parlant, le C# n'a pas de destructeur (je crois que la spécification du C# est confuse sur ce point). Le finalizer de C# ressemble à un destructeur C++ mais, comme vous le dites, il est non déterministe. C# a un nettoyage déterministe sous la forme de IDisposable::Dispose (mais cela ne s'appelle toujours pas un destructeur).

C++/CLI possède des destructeurs déterministes, qui ressemblent aux destructeurs C++. Au niveau de la CLI, ils correspondent à IDisposable::Dispose() ( IDisposable est mis en œuvre pour vous). C++/CLI possède des finaliseurs non déterministes, qui ressemblent à des destructeurs mais utilisent le préfixe ! au lieu du préfixe ^.

Le fait que C++/CLI utilise la même syntaxe pour les destructeurs que C# pour les finaliseurs peut être un peu déroutant - mais cela correspond mieux au C++, qui a une forte tradition de destruction déterministe.

Malheureusement, l'absence de définitions universelles de ces termes signifie que vous devez toujours clarifier ce dont vous parlez. Personnellement, j'utilise toujours le mot finaliseur quand on parle du concept C# et de la réserve destructeur pour les contextes où il implique définitivement une destruction déterministe.

[Mise à jour] Depuis mon premier message ici, Eric Lippert a publié sa réponse (la réponse acceptée) et a poursuivi avec un message de la part d'Eric Lippert. article de blog sur la même chose. Je suis heureux de voir que nous sommes d'accord :-)

3voto

Steve Cooper Points 6637

Je pense que le "destructeur" est le code C# et que le "finalisateur" est la méthode CIL compilée. Le compilateur C# transforme un destructeur en un finalisateur.

La spécification du langage C# définit un "destructeur" comme une méthode d'instance C# sur une classe. Le terme 'destructeur' fait donc partie de la grammaire C# -- les destructeurs sont un objet linguistique apparaissant dans le code source.

Un destructeur est un membre qui met en œuvre les actions requises pour détruire une instance d'une classe. Les destructeurs ne peuvent pas avoir de paramètres, ni de modificateurs d'accessibilité, et ils ne peuvent pas être invoqués explicitement. Le destructeur d'une instance est invoqué automatiquement lors de la collecte des déchets.

Un "finalisateur" est un terme utilisé dans le Common Language Runtime, par exemple dans les appels à GC.WaitForPendingFinalizers() Ce terme fait référence à tout langage .net, et pas seulement à C#. Tout type de référence .net peut avoir un finalisateur. Pour une classe C# (l'artefact du code source), le destructeur est compilé dans la méthode CIL qui est le finalisateur du type CLR.

Ou plus succinctement, destructeur est de finaliseur comme code source est de code machine ;)

3voto

Konamiman Points 20578

Si nous nous en tenons à la définition "déterministe" des destructeurs, alors je dirais que dans .NET les objets n'ont pas de destructeurs, à moins qu'ils ne soient explicitement implémentés par l'utilisation de l'interface IDisposable .

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X