11
votes

Appeler C ++ / CLI Supprimer sur objet C #

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.

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)?


0 commentaires

4 Réponses :


17
votes

Je dirais le Idisposable 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.

en C ++ / CLI, si vous déclarez un type géré ( Classe de référence et similaire), Idisposable est implémenté à l'aide de la syntaxe destructeurs et Dispose ( ) est appelé à l'aide du mot-clé Supprimer . Si vous déclarez un tel objet d'un type géré localement (sans utiliser l'opérateur ^ ou gcnew ), C ++ / cli appelle même automatiquement Dispose () Pour vous lorsque l'objet sort de la portée. De cette façon, C ++ / CLI est plus pratique que c #.

Vous ne pourrez pas appeler Supprimer sur l'objet lors de l'utilisation C #, vous devez appeler Disposer () manuellement dessus. Une autre façon de disposer de Idisposable Objets est le en utilisant bloc.

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.

La meilleure approche pour traiter des ressources non gérées est probablement une combinaison des deux. Voir ici pour l'approche recommandée:
http://msdn.microsoft.com/en-us/library/b1yfkh5e (v = vs.100) .aspx

Remarque, cependant que lorsque vous utilisez Idisposable , 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).

Je viens de trouver un article en expliquant les différences entre C ++ / CLI et C #. Vous pourriez le trouver intéressant:
http://weblogs.thinkTecture.com/cnagel/2006/04/ccli- finaliser-and-disposer.html


4 commentaires

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 sur les objets implémentatrisant Idisposable appelle leur Dispose () méthode. C'est juste la syntaxe spéciale de C ++ / CLI pour cela.



0
votes

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 ().

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.


0 commentaires

1
votes

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();


2 commentaires

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



4
votes

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.

Le finisseur C ++ / CLI (! FOO) est le destructeur C #.

de sorte que l'opérateur C ++ / CLI Supprimer 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é . Difficile de voir du code source alors payez une attention particulière ou regardez l'IL généré avec ildasm.exe


1 commentaires

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 .