Menu
Coddy logo textTech

IDisposable & using-Anweisung

Teil des Abschnitts Objektorientierte Programmierung der C#-Journey von Coddy — Lektion 45 von 70.

Einige Objekte halten Ressourcen fest, die der Garbage Collector nicht automatisch bereinigen kann – Dateihandles, Datenbankverbindungen, Netzwerk-Sockets. Die Schnittstelle IDisposable bietet eine standardisierte Möglichkeit, diese Ressourcen freizugeben, wenn Sie mit ihnen fertig sind.

Eine Klasse implementiert IDisposable, indem sie eine Dispose()-Methode bereitstellt:

public class FileHandler : IDisposable
{
    private bool disposed = false;
    
    public void Dispose()
    {
        if (!disposed)
        {
            Console.WriteLine("Releasing resources...");
            disposed = true;
        }
    }
}

Sie könnten Dispose() manuell aufrufen, aber was passiert, wenn eine Exception auftritt, bevor Sie diese Zeile erreichen? Die using-Anweisung garantiert, dass die Bereinigung erfolgt, selbst wenn etwas schiefgeht:

using (FileHandler handler = new FileHandler())
{
    // Mit dem Handler arbeiten
}  // Dispose() wird hier automatisch aufgerufen

Modernes C# bietet eine sauberere Syntax mit der using-Deklaration, die das Objekt freigibt, wenn es den Gültigkeitsbereich verlässt:

void ProcessFile()
{
    using FileHandler handler = new FileHandler();
    // Mit dem Handler arbeiten
}  // Dispose() wird aufgerufen, wenn die Methode beendet wird

Die using-Anweisung funktioniert mit jedem Typ, der IDisposable implementiert. Integrierte Klassen wie StreamReader, SqlConnection und HttpClient implementieren alle diese Schnittstelle, was eine ordnungsgemäße Ressourcenverwaltung unkompliziert und zuverlässig macht.

challenge icon

Aufgabe

Einfach

Lassen Sie uns einen Datenbankverbindungssimulator erstellen, der die ordnungsgemäße Ressourcenverwaltung mithilfe der Schnittstelle IDisposable und der using-Anweisung demonstriert. Sie werden eine Klasse erstellen, die verfolgt, wann Verbindungen geöffnet und geschlossen werden, um sicherzustellen, dass Ressourcen immer ordnungsgemäß freigegeben werden.

Sie werden Ihren Code auf zwei Dateien aufteilen:

  • DatabaseConnection.cs: Erstellen Sie eine Klasse DatabaseConnection im Namespace DataAccess, die IDisposable implementiert. Ihre Verbindung sollte:
    • Über eine Eigenschaft ConnectionName (String, schreibgeschützt) verfügen, die über den Konstruktor gesetzt wird
    • Mithilfe eines privaten booleschen Feldes verfolgen, ob die Verbindung bereits freigegeben (disposed) wurde
    • Connection opened: {ConnectionName} ausgeben, wenn das Objekt erstellt wird (im Konstruktor)
    • Die Methode Dispose() implementieren, um Connection closed: {ConnectionName} auszugeben – aber nur, wenn sie nicht bereits freigegeben wurde (um eine doppelte Freigabe zu verhindern)
    • Über eine Methode Query(string sql) verfügen, die Executing on {ConnectionName}: {sql} zurückgibt
  • Program.cs: Demonstrieren Sie in Ihrer Hauptdatei die ordnungsgemäße Ressourcenverwaltung, indem Sie die using-Anweisung mit Ihrer Datenbankverbindung verwenden. Erstellen Sie eine Verbindung, führen Sie eine Abfrage aus und lassen Sie den using-Block die Bereinigung automatisch übernehmen.

Sie erhalten zwei Eingaben:

  • Den Verbindungsnamen (z. B. MainDB)
  • Die auszuführende SQL-Abfrage (z. B. SELECT * FROM Users)

Verwenden Sie eine using-Anweisung, um Ihre Verbindung zu erstellen. Rufen Sie innerhalb des Blocks die Methode Query auf und geben Sie deren Ergebnis aus. Wenn der using-Block endet, wird Dispose() automatisch aufgerufen.

Wenn die Eingaben beispielsweise MainDB und SELECT * FROM Users lauten, sollte die Ausgabe wie folgt aussehen:

Connection opened: MainDB
Executing on MainDB: SELECT * FROM Users
Connection closed: MainDB

Beachten Sie, wie die Verbindung automatisch geschlossen wird, wenn der using-Block endet – Sie müssen nie daran denken, Dispose() manuell aufzurufen. Dieses Muster stellt sicher, dass Ressourcen immer bereinigt werden, selbst wenn innerhalb des Blocks eine Exception auftritt!

Spickzettel

Die Schnittstelle IDisposable bietet eine Standardmethode zur Freigabe von Ressourcen, die der Garbage Collector nicht automatisch bereinigen kann (Dateihandles, Datenbankverbindungen, Netzwerksockets).

Eine Klasse implementiert IDisposable, indem sie eine Dispose()-Methode bereitstellt:

public class FileHandler : IDisposable
{
    private bool disposed = false;
    
    public void Dispose()
    {
        if (!disposed)
        {
            Console.WriteLine("Releasing resources...");
            disposed = true;
        }
    }
}

Die using-Anweisung garantiert, dass die Bereinigung automatisch erfolgt, selbst wenn Ausnahmen auftreten:

using (FileHandler handler = new FileHandler())
{
    // Mit dem Handler arbeiten
}  // Dispose() wird hier automatisch aufgerufen

Modernes C# bietet eine sauberere Syntax mit der using-Deklaration:

void ProcessFile()
{
    using FileHandler handler = new FileHandler();
    // Mit dem Handler arbeiten
}  // Dispose() wird aufgerufen, wenn die Methode beendet wird

Die using-Anweisung funktioniert mit jedem Typ, der IDisposable implementiert, einschließlich integrierter Klassen wie StreamReader, SqlConnection und HttpClient.

Probier es selbst

using System;
using DataAccess;

class Program
{
    public static void Main(string[] args)
    {
        string connectionName = Console.ReadLine();
        string sqlQuery = Console.ReadLine();
        
        // TODO: Verwenden Sie eine 'using'-Anweisung, um eine DatabaseConnection zu erstellen
        // Innerhalb des using-Blocks:
        // 1. Rufen Sie die Query-Methode mit der sqlQuery auf
        // 2. Geben Sie das Ergebnis der Query-Methode aus
        // Die Dispose-Methode wird automatisch aufgerufen, wenn der using-Block endet
        
    }
}
quiz iconTeste dich selbst

Diese Lektion enthält ein kurzes Quiz. Starte die Lektion, um es zu beantworten und deinen Fortschritt zu speichern.

Alle Lektionen in Objektorientierte Programmierung