J’ai une classe qui a une propriété du type SqlConnection
. SqlConnection
implémente IDisposable
. J’ai des questions suivantes:
IDisposable
simplement parce qu’elle a la propriété de type IDisposable
? Si oui, dois-je éliminer la propriété de manière explicite lorsque je dispose d’une instance de ma classe? Par exemple
public class Helper : IDisposable { // Assume that it's ANY OTHER IDisposable type. SqlConnection is just an example. public SqlConnection SqlConnection { get; set; } public void Dispose() { if (SqlConnection!= null) { SqlConnection.Dispose(); } } }
Remarque: Je sais qu’il faut suivre un schéma lors de la mise en œuvre d’ IDisposable
mais ma question est très spécifique au cas mentionné ci-dessus.
Ça dépend Si votre classe crée et possède l’ IDisposable
elle doit en disposer (les deux réponses sont donc “oui” ). Si votre classe utilise simplement IDisposable
elle ne doit pas en disposer (la première réponse est généralement “non” et la deuxième réponse est “non” ).
Dans votre cas, il semble que la classe Helper
public class Helper { // Note, that you can assign any arbitrary Connection via this property public SqlConnection SqlConnection { get; set; } .... }
utilise simplement SqlConnection
(car il fournit “set”) comme
// It's not helper that owns SqlConnection using (SqlConnection con = new SqlConnection(...)) { ... // helper just uses Connection, so helper must not dispose it Helper helper = new Helper() { SqlConnection = con; }; ... }
il ne faut donc pas disposer de la connexion. Au contraire, une classe comme ça
public class Helper: IDisposable { private SqlConnection m_SqlConnection; // Note the absence of public "set" public SqlConnection SqlConnection { get { return m_SqlConnection; } } ... }
est propriétaire de SqlConnection
et est donc responsable de son élimination:
using (Helper helper = new Helper(...)) { ... // it's helper that owns SqlConnection SqlConnection con = helper.SqlConnection; ... }
Oui
Oui
Il existe même une règle d’parsing de code pour cela: CA1001: Les types possédant des champs à disposition doivent être à disposition .
Une classe implémente l’interface IDisposable pour disposer des ressources non gérées qu’elle possède. Un champ d’instance de type IDisposable indique qu’il est propriétaire d’une ressource non gérée. Une classe qui déclare un champ IDisposable possède indirectement une ressource non gérée et doit implémenter l’interface IDisposable.
EDIT: la réponse ci-dessus est toujours valable pour les membres IDisposable
appartenant à la classe parente.
Cela dit, la propriété d’un membre est un peu vague pour les propriétés publiques comme la vôtre: si l’instance SqlConnection
est créée en dehors de votre classe, il est probable que votre classe ne possède pas l’instance, mais personne ne le sait, sauf vous.
Il existe un exemple amusant StreamWriter
si un membre IDisposable
appartient ou non à sa classe parent: StreamWriter
. Il y a beaucoup de questions à ce sujet, voir par exemple ce fil: Est-il possible de fermer un StreamWriter sans fermer sa BaseStream?
Maintenant, il existe même un paramètre leaveOpen
afin que StreamWriter
ne dispose pas de son stream de base.
Oui pour les deux – si votre classe est responsable du cycle de vie d’un champ membre, elle doit alors appeler Dispose
sur cet object, ce qui signifie que votre classe doit implémenter IDisposable
afin que le membre puisse être supprimé au bon moment.
Toutefois, notez que vous ne souhaitez probablement pas utiliser une propriété configurable publique pour un tel membre, car tout le monde peut alors effacer, supprimer, désactiver, réinitialiser directement ce champ. Votre classe doit conserver le contrôle de ce champ, ce qui signifie qu’il ne doit être paramétrable que de l’intérieur de la classe elle-même (idéalement, en utilisant un champ private readonly
ou une propriété readonly).