Je suis au milieu de la conversion du code de C ++ / CLI en C #. L'un des objets a un destructeur de la version C ++ / CLI. Un autre code C ++ / CLI appelle "Supprimer" sur cet objet après utilisation. P>
Quelle méthode dois-je implémenter dans la version C # de cet objet afin que ces "Supprimer" continuent de fonctionner de la même manière (Idisposable.Dispose, le finaliseur ou autre chose qui me manque)? P>
4 Réponses :
Je dirais le Idisposable code>
interface est quoi Vous recherchez si vous avez besoin d'une élimination déterministe des ressources. C'est généralement le cas avec des ressources non gérées, telles que des poignées non gérées qui doivent être fermées, des flux ou des connexions de base de données. p>
en C ++ / CLI, si vous déclarez un type géré ( Vous ne pourrez pas appeler Le finisseur (implémenté dans C # à l'aide de la syntaxe destructeurs) n'est pas identique à un destructeur C ++, car il n'est pas déterministe quand il sera appelé. Les objets avec un finisseur sont fondamentalement mis en file d'attente jusqu'à ce que le fil finisseur décide d'appeler leur finisseur, de manière efficace que vous ne savez jamais exactement quand cela s'appelle. P>
La meilleure approche pour traiter des ressources non gérées est probablement une combinaison des deux. Voir ici pour l'approche recommandée: Remarque, cependant que lorsque vous utilisez Je viens de trouver un article en expliquant les différences entre C ++ / CLI et C #. Vous pourriez le trouver intéressant: Classe de référence code> et similaire),
Idisposable code> est implémenté à l'aide de la syntaxe destructeurs et
Dispose ( ) code> est appelé à l'aide du mot-clé
Supprimer code>. Si vous déclarez un tel objet d'un type géré localement (sans utiliser l'opérateur
^ code> ou
gcnew code>), C ++ / cli appelle même automatiquement
Dispose () Code > Pour vous lorsque l'objet sort de la portée. De cette façon, C ++ / CLI est plus pratique que c #. P>
Supprimer code> sur l'objet lors de l'utilisation C #, vous devez appeler
Disposer () code> manuellement dessus. Une autre façon de disposer de
Idisposable code> Objets est le
en utilisant code>
bloc. p>
http://msdn.microsoft.com/en-us/library/b1yfkh5e (v = vs.100) .aspx p>
Idisposable code>, même si vous pouvez disposer des ressources non gérées de manière déterministe, des objets gérés doivent encore être collectés par le collecteur des ordures (non déterminisciquement). p>
http://weblogs.thinkTecture.com/cnagel/2006/04/ccli- finaliser-and-disposer.html p>
La sémantique C ++ / CLI Stack travaille également sur des membres de la classe, pas seulement des locaux. Il n'y a pas de moyen simple de dupliquer cela en C #.
Je ne savais pas que (n'utilisant pas très souvent C ++ / CLI). Merci pour l'info :)
Je viens de relire la réponse et il y a quelque chose dont j'ai besoin de clarification: si ma classe est définie dans c # (et implémente Idisposable), vais-je appeler "Supprimer" sur celui-ci lors de l'utilisation d'une autre classe C ++ / CLI? Merci!
@Danielgabriel Oui, appelant Supprimer code> sur les objets implémentatrisant
Idisposable code> appelle leur
Dispose () code> méthode. C'est juste la syntaxe spéciale de C ++ / CLI pour cela.
Pour moi, cela dépend vraiment de ce que fait le destructeur. Si cela fait quelque chose comme la libération d'une ressource non gérée (connexions SQL ou de fichiers, par exemple), je voudrais mettre en œuvre Idisose et fermer la connexion dans la méthode Dispose (). P>
Si cela détruit d'autres objets qui ne nécessitent aucun nettoyage explicite, je quitterais simplement le destructeur et laissez le gc la gérer. P>
C # ne fournit pas les mêmes outils, mais il fournit des modèles pour vous: Si votre DTOR fera la fermeture d'un flux, des pointeurs delinging, ou des états de réglage de manière appropriée, je sens que l'interface code> Idisposable code> est un bon ajustement:
// C# void Dispose() { _stream.Close(); _ptr = null; _running = false; } // with obj.Dispose();
Il convient de C ++ / CLI, qui est déjà une langue gérée avec une collecte des ordures non déterministes. Mais .NET ajoute un modèle d'élimination déterministe, qui a un excellent support linguistique en C ++ / CLI, et il demande comment traduire cela en C #. C # a également un soutien linguistique pour l'élimination, mais pas aussi élégant.
Merci d'avoir souligné cela - oui, il a un motif et je l'ai dirigé vers cette tendance avec des cas appropriés. Je vais résoudre ma réponse pour refléter qu'il vient de C ++ / CLI
Il y a une inadéquation de terminologie entre C ++ / CLI et C #. Le destructeur C ++ / CLI (~ FOO) est la mise en œuvre de la méthode Idisposable.Dispose (). Une classe C ++ / CLI ne met pas explicitement implémente Idisposable, elle est automatique de la présence d'un destructeur. P>
Le finisseur C ++ / CLI (! FOO) est le destructeur C #. P>
de sorte que l'opérateur C ++ / CLI Supprimer em> est équivalent à l'appel de la méthode Disposer (). Méfiez-vous des sémantiques de pile en C ++ / CLI, déclenchées par une variable locale d'un type de référence sans le chapeau. Le compilateur génère un appel caché à disposer () à la fin du bloc d'étendue. Qui est équivalent au c # en utilisant le mot-clé em>. Difficile de voir du code source alors payez une attention particulière ou regardez l'IL généré avec ildasm.exe P>
Juste une clarification: bien que la documentation C # parle de "destructeurs", c # n'a vraiment pas de destructeurs. Utiliser la notation destructeurs en C # crée un finisseur. Et la sémantique C ++ / CLI Stack sont beaucoup plus puissantes que c # en utilisant des blocs code>.