IDisposable et l'instruction using
Fait partie de la section Programmation Orientée Objet du Journey C# de Coddy — leçon 45 sur 70.
Certains objets conservent des ressources que le ramasse-miettes (garbage collector) ne peut pas nettoyer automatiquement - descripteurs de fichiers, connexions à des bases de données, sockets réseau. L'interface IDisposable fournit un moyen standard de libérer ces ressources lorsque vous avez fini de les utiliser.
Une classe implémente IDisposable en fournissant une méthode Dispose() :
public class FileHandler : IDisposable
{
private bool disposed = false;
public void Dispose()
{
if (!disposed)
{
Console.WriteLine("Releasing resources...");
disposed = true;
}
}
}Vous pourriez appeler Dispose() manuellement, mais que se passe-t-il si une exception survient avant d'atteindre cette ligne ? L'instruction using garantit que le nettoyage est effectué, même quand les choses tournent mal :
using (FileHandler handler = new FileHandler())
{
// Travailler avec le gestionnaire
} // Dispose() est appelé automatiquement iciLe C# moderne offre une syntaxe plus propre avec la déclaration using, qui libère l'objet lorsqu'il sort de la portée :
void ProcessFile()
{
using FileHandler handler = new FileHandler();
// Travailler avec handler
} // Dispose() est appelé à la sortie de la méthodeL'instruction using fonctionne avec n'importe quel type qui implémente IDisposable. Les classes intégrées comme StreamReader, SqlConnection et HttpClient implémentent toutes cette interface, ce qui rend la gestion appropriée des ressources simple et fiable.
Défi
FacileConstruisons un simulateur de connexion à une base de données qui démontre une gestion appropriée des ressources à l'aide de l'interface IDisposable et de l'instruction using. Vous allez créer une classe qui suit l'ouverture et la fermeture des connexions, garantissant que les ressources sont toujours correctement libérées.
Vous organiserez votre code sur deux fichiers :
DatabaseConnection.cs: Créez une classeDatabaseConnectiondans l'espace de nomsDataAccessqui implémenteIDisposable. Votre connexion doit :- Avoir une propriété
ConnectionName(chaîne de caractères, en lecture seule) définie via le constructeur - Suivre si la connexion a été libérée à l'aide d'un champ booléen privé
- Afficher
Connection opened: {ConnectionName}lors de la création de l'objet (dans le constructeur) - Implémenter la méthode
Dispose()pour afficherConnection closed: {ConnectionName}- mais seulement si elle n'a pas déjà été libérée (pour éviter une double libération) - Avoir une méthode
Query(string sql)qui retourneExecuting on {ConnectionName}: {sql}
- Avoir une propriété
Program.cs: Dans votre fichier principal, démontrez une gestion appropriée des ressources en utilisant l'instructionusingavec votre connexion à la base de données. Créez une connexion, exécutez une requête et laissez le blocusinggérer automatiquement le nettoyage.
Vous recevrez deux entrées :
- Le nom de la connexion (par exemple,
MainDB) - La requête SQL à exécuter (par exemple,
SELECT * FROM Users)
Utilisez une instruction using pour créer votre connexion. À l'intérieur du bloc, appelez la méthode Query et affichez son résultat. Lorsque le bloc using se termine, Dispose() sera appelé automatiquement.
Par exemple, si les entrées sont MainDB et SELECT * FROM Users, la sortie devrait être :
Connection opened: MainDB
Executing on MainDB: SELECT * FROM Users
Connection closed: MainDBRemarquez comment la connexion est automatiquement fermée lorsque le bloc using se termine - vous n'avez jamais besoin de vous rappeler d'appeler Dispose() manuellement. Ce modèle garantit que les ressources sont toujours nettoyées, même si une exception se produit à l'intérieur du bloc !
Aide-mémoire
L'interface IDisposable fournit un moyen standard de libérer les ressources que le ramasse-miettes (garbage collector) ne peut pas nettoyer automatiquement (descripteurs de fichiers, connexions à des bases de données, sockets réseau).
Une classe implémente IDisposable en fournissant une méthode Dispose() :
public class FileHandler : IDisposable
{
private bool disposed = false;
public void Dispose()
{
if (!disposed)
{
Console.WriteLine("Releasing resources...");
disposed = true;
}
}
}L'instruction using garantit que le nettoyage s'effectue automatiquement, même en cas d'exceptions :
using (FileHandler handler = new FileHandler())
{
// Travailler avec le gestionnaire
} // Dispose() est appelé automatiquement iciLe C# moderne offre une syntaxe plus propre avec la déclaration using :
void ProcessFile()
{
using FileHandler handler = new FileHandler();
// Travailler avec le gestionnaire
} // Dispose() est appelé à la sortie de la méthodeL'instruction using fonctionne avec n'importe quel type implémentant IDisposable, y compris les classes intégrées comme StreamReader, SqlConnection et HttpClient.
Essayez vous-même
using System;
using DataAccess;
class Program
{
public static void Main(string[] args)
{
string connectionName = Console.ReadLine();
string sqlQuery = Console.ReadLine();
// TODO: Utiliser une instruction 'using' pour créer une DatabaseConnection
// À l'intérieur du bloc using :
// 1. Appeler la méthode Query avec le sqlQuery
// 2. Afficher le résultat de la méthode Query
// La méthode Dispose sera appelée automatiquement à la fin du bloc using
}
}
Cette leçon comprend un petit quiz. Commencez la leçon pour y répondre et suivre votre progression.
Toutes les leçons de Programmation Orientée Objet
1Fondamentaux de la POO
Fichiers externesEspaces de noms et directivesIntro aux classes et objetsLe mot-clé 'this'Méthodes et paramètresChamps vs PropriétésConstructeursInitialiseurs d'objetsRécapitulatif - Calculatrice simple4Héritage
Syntaxe de base de l'héritage (:)Le mot-clé 'base'Mots-clés Virtual & OverrideClasses scelléesLa classe de base 'object'Récapitulatif - Hiérarchie des employés7Fonctionnalités avancées
Surcharge d'opérateursIndexeurs (this[])Redéfinition de ToString()Méthodes d'extensionRécapitulatif - Liste personnalisée10Patrons de conception - Partie 1
Introduction aux patrons de conceptionSingleton Thread-SafePatron FabriquePatron Observateur (Événements)Patron Stratégie2Propriétés et membres statiques
Propriétés auto-implémentéesPropriétés en lecture/écriture seuleChamps et méthodes statiquesClasses statiquesMembres à corps d'expression5Polymorphisme & Interfaces
Polymorphisme : Compilation vs ExécutionInterface vs Classe AbstraiteInterfaces MultiplesInterfaces ExplicitesUpcasting & DowncastingRécapitulatif - Calculateur de Formes8Concepts avancés de la POO
Composition plutôt qu'héritageGénériques (Classes et Méthodes)Délégués et ÉvénementsAttributs et RéflexionIDisposable et l'instruction usingBases de l'Injection de Dépendances11Patrons de conception, Partie 2
Patron CommandePatron AdaptateurPatron DécorateurPatron Méthode TemplatePatron ÉtatPatron Composite3Architecture des classes
Données d'instance vs statiquesMots-clés 'readonly' & 'const'Champs de supportRécapitulatif - Gestionnaire de compte bancaire6Encapsulation
Modificateurs d'accèsPropriétés pour l'encapsulationImplémentation du masquage de donnéesPatterns d'immuabilitéRécapitulatif - Dossiers d'étudiants12Projet : Système de gestion de bibliothèque
Structure du projetModèles Livre et Utilisateur