Hinweis
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, sich anzumelden oder das Verzeichnis zu wechseln.
Für den Zugriff auf diese Seite ist eine Autorisierung erforderlich. Sie können versuchen, das Verzeichnis zu wechseln.
Der Garbage Collector (GC) der Common Language Runtime gibt den von verwalteten Objekten verwendeten Speicher frei. In der Regel implementieren Typen, die nicht verwaltete Ressourcen verwenden, die oder IAsyncDisposable die IDisposable Schnittstelle, damit die nicht verwalteten Ressourcen erneut beansprucht werden können. Wenn Sie mit der Verwendung eines Objekts fertig sind, das implementiert IDisposablewird, rufen Sie die Objekt Dispose - oder DisposeAsync Implementierung auf, um explizit eine Bereinigung durchzuführen. Sie können dies auf eine von zwei Arten tun:
- Mit der C#
using
-Anweisung oder -Deklaration (Using
in Visual Basic). - Durch Implementieren eines
try/finally
Blocks und Aufrufen der Dispose Oder-Methode DisposeAsync in derfinally
.
Von Bedeutung
Die GC entsorgt Ihre Objekte nicht , da sie keine Kenntnisse IDisposable.Dispose() hat oder IAsyncDisposable.DisposeAsync(). Die GC weiß nur, ob ein Objekt abgeschlossen werden kann (d. h. es definiert eine Object.Finalize() Methode), und wenn der Finalizer des Objekts aufgerufen werden muss. Weitere Informationen finden Sie unter "Funktionsweise der Finalisierung". Weitere Details zur Implementierung Dispose
und DisposeAsync
finden Sie unter:
Objekte, die implementieren System.IDisposable oder System.IAsyncDisposable immer ordnungsgemäß verworfen werden sollten, unabhängig von variablen Bereichsdefinitionen, sofern nicht anders angegeben. Typen, die einen Finalizer definieren, um nicht verwaltete Ressourcen freizugeben, rufen GC.SuppressFinalize in der Regel von deren Dispose
Oder DisposeAsync
implementierung ab. Das Aufrufen SuppressFinalize gibt an, dass der Finalizer bereits ausgeführt wurde, und das Objekt sollte nicht für die Finalisierung heraufgestuft werden.
Die using-Anweisung
Die using
Anweisung in C# und die Using
Anweisung in Visual Basic vereinfachen den Code, den Sie schreiben müssen, um ein Objekt zu bereinigen. Die using
Anweisung ruft eine oder mehrere Ressourcen ab, führt die von Ihnen angegebenen Anweisungen aus und entfernt das Objekt automatisch. Die using
Anweisung ist jedoch nur für Objekte nützlich, die im Rahmen der Methode verwendet werden, in der sie erstellt werden.
Im folgenden Beispiel wird die using
Anweisung verwendet, um ein System.IO.StreamReader Objekt zu erstellen und freizugeben.
using System.IO;
class UsingStatement
{
static void Main()
{
var buffer = new char[50];
using (StreamReader streamReader = new("file1.txt"))
{
int charsRead = 0;
while (streamReader.Peek() != -1)
{
charsRead = streamReader.Read(buffer, 0, buffer.Length);
//
// Process characters read.
//
}
}
}
}
Imports System.IO
Module UsingStatement
Public Sub Main()
Dim buffer(49) As Char
Using streamReader As New StreamReader("File1.txt")
Dim charsRead As Integer
Do While streamReader.Peek() <> -1
charsRead = streamReader.Read(buffer, 0, buffer.Length)
'
' Process characters read.
'
Loop
End Using
End Sub
End Module
Eine using
Deklaration ist eine alternative Syntax, die verfügbar ist, wenn die geschweiften Klammern entfernt werden, und die Bereichsdefinition ist implizit.
using System.IO;
class UsingDeclaration
{
static void Main()
{
var buffer = new char[50];
using StreamReader streamReader = new("file1.txt");
int charsRead = 0;
while (streamReader.Peek() != -1)
{
charsRead = streamReader.Read(buffer, 0, buffer.Length);
//
// Process characters read.
//
}
}
}
Obwohl die StreamReader Klasse die IDisposable Schnittstelle implementiert, die angibt, dass sie eine nicht verwaltete Ressource verwendet, ruft das Beispiel die StreamReader.Dispose Methode nicht explizit auf. Wenn der C#- oder Visual Basic-Compiler auf die using
Anweisung trifft, gibt er Zwischensprache (IL) aus, die dem folgenden Code entspricht, der explizit einen try/finally
Block enthält.
using System.IO;
class TryFinallyGenerated
{
static void Main()
{
var buffer = new char[50];
StreamReader? streamReader = null;
try
{
streamReader = new StreamReader("file1.txt");
int charsRead = 0;
while (streamReader.Peek() != -1)
{
charsRead = streamReader.Read(buffer, 0, buffer.Length);
//
// Process characters read.
//
}
}
finally
{
// If non-null, call the object's Dispose method.
streamReader?.Dispose();
}
}
}
Imports System.IO
Module TryFinallyGenerated
Public Sub Main()
Dim buffer(49) As Char
Dim streamReader As New StreamReader("File1.txt")
Try
Dim charsRead As Integer
Do While streamReader.Peek() <> -1
charsRead = streamReader.Read(buffer, 0, buffer.Length)
'
' Process characters read.
'
Loop
Finally
If streamReader IsNot Nothing Then DirectCast(streamReader, IDisposable).Dispose()
End Try
End Sub
End Module
Mit der C# using
-Anweisung können Sie auch mehrere Ressourcen in einer einzelnen Anweisung abrufen, die intern geschachtelten using
Anweisungen entspricht. Im folgenden Beispiel werden zwei StreamReader Objekte instanziiert, um den Inhalt von zwei verschiedenen Dateien zu lesen.
using System.IO;
class SingleStatementMultiple
{
static void Main()
{
var buffer1 = new char[50];
var buffer2 = new char[50];
using StreamReader version1 = new("file1.txt"),
version2 = new("file2.txt");
int charsRead1, charsRead2 = 0;
while (version1.Peek() != -1 && version2.Peek() != -1)
{
charsRead1 = version1.Read(buffer1, 0, buffer1.Length);
charsRead2 = version2.Read(buffer2, 0, buffer2.Length);
//
// Process characters read.
//
}
}
}
Try/finally block
Anstatt einen try/finally
Block in eine using
Anweisung umzuschließen, können Sie den try/finally
Block direkt implementieren. Möglicherweise handelt es sich um Ihren persönlichen Codierungsstil, oder Sie möchten dies aus einem der folgenden Gründe tun:
- So fügen Sie einen
catch
Block zum Behandeln von Ausnahmen in dentry
Block ein. Andernfalls werden alle ausnahmen, die innerhalb derusing
Anweisung ausgelöst werden, nicht behandelt. - Um ein Objekt zu instanziieren, das implementiert IDisposable , dessen Bereich nicht lokal für den Block ist, in dem es deklariert wird.
Das folgende Beispiel ähnelt dem vorherigen Beispiel, mit der Ausnahme, dass ein try/catch/finally
Block zum Instanziieren, Verwenden und Löschen eines StreamReader Objekts verwendet wird, und zum Behandeln von Ausnahmen, die vom StreamReader Konstruktor und dessen ReadToEnd Methode ausgelöst werden. Der Code im finally
Block überprüft, ob das implementierte IDisposable Objekt nicht null
vor dem Aufrufen der Dispose Methode erfolgt. Wenn dies nicht möglich ist, kann dies zur Laufzeit zu einer NullReferenceException Ausnahme führen.
using System;
using System.Globalization;
using System.IO;
class TryExplicitCatchFinally
{
static void Main()
{
StreamReader? streamReader = null;
try
{
streamReader = new StreamReader("file1.txt");
string contents = streamReader.ReadToEnd();
var info = new StringInfo(contents);
Console.WriteLine($"The file has {info.LengthInTextElements} text elements.");
}
catch (FileNotFoundException)
{
Console.WriteLine("The file cannot be found.");
}
catch (IOException)
{
Console.WriteLine("An I/O error has occurred.");
}
catch (OutOfMemoryException)
{
Console.WriteLine("There is insufficient memory to read the file.");
}
finally
{
streamReader?.Dispose();
}
}
}
Imports System.Globalization
Imports System.IO
Module TryExplicitCatchFinally
Sub Main()
Dim streamReader As StreamReader = Nothing
Try
streamReader = New StreamReader("file1.txt")
Dim contents As String = streamReader.ReadToEnd()
Dim info As StringInfo = New StringInfo(contents)
Console.WriteLine($"The file has {info.LengthInTextElements} text elements.")
Catch e As FileNotFoundException
Console.WriteLine("The file cannot be found.")
Catch e As IOException
Console.WriteLine("An I/O error has occurred.")
Catch e As OutOfMemoryException
Console.WriteLine("There is insufficient memory to read the file.")
Finally
If streamReader IsNot Nothing Then streamReader.Dispose()
End Try
End Sub
End Module
Sie können diesem grundlegenden Muster folgen, wenn Sie einen try/finally
Block implementieren oder implementieren möchten, da Ihre Programmiersprache keine using
Anweisung unterstützt, aber direkte Aufrufe an die Dispose Methode zulässt.
IDisposable-Instanzmember
Wenn eine Klasse ein Instanzfeld oder eine Instanzeigenschaft besitzt und deren Typ implementiert wird IDisposable, sollte die Klasse auch implementiert werden IDisposable. Weitere Informationen finden Sie unter Implementieren einer Löschweiterung.