Notatka
Dostęp do tej strony wymaga autoryzacji. Może spróbować zalogować się lub zmienić katalogi.
Dostęp do tej strony wymaga autoryzacji. Możesz spróbować zmienić katalogi.
| Właściwości | Wartość |
|---|---|
| Identyfikator reguły | CA1816 |
| Tytuł | Poprawnie wywołaj metodę GC.SuppressFinalize |
| Kategoria | Użycie |
| Poprawka łamiąca lub nienaruszająca | Niezgodność |
| Domyślnie włączone na platformie .NET 10 | Jako sugestia |
| Zastosowane języki | C# i Visual Basic |
Przyczyna
Naruszenia tej reguły mogą być spowodowane przez:
W niezaznaczonej klasie jest to metoda, która jest implementacją IDisposable.Dispose i nie wywołuje GC.SuppressFinalize.
Metoda, która nie jest implementacją IDisposable.Dispose i wywołuje GC.SuppressFinalize.
Metoda, która wywołuje GC.SuppressFinalize i przekazuje coś innego niż this (C#) lub Me (Visual Basic).
Opis reguły
Metoda IDisposable.Dispose umożliwia użytkownikom wydawanie zasobów w dowolnym momencie, zanim obiekt stanie się dostępny do odzyskiwania pamięci. IDisposable.Dispose Jeśli metoda zostanie wywołana, zwalnia zasoby obiektu. To sprawia, że finalizacja jest niepotrzebna. IDisposable.Dispose powinien wywołać metodę GC.SuppressFinalize, aby garbage collector nie wywołał finalizatora obiektu.
Aby zapobiec konieczności ponownego implementowania IDisposable w typach pochodnych z finalizatorami i jego wywołaniu, niezapieczętowane typy bez finalizatorów powinny nadal wywoływać GC.SuppressFinalize.
Jak naprawić naruszenia
Aby naprawić naruszenie tej reguły:
Jeśli metoda jest implementacją Dispose, dodaj wywołanie do GC.SuppressFinalize.
Jeśli metoda nie jest implementacją Dispose, usuń wywołanie GC.SuppressFinalize lub przenieś je do implementacji Dispose typu.
Zmień wszystkie wywołania tak, aby przekazywać GC.SuppressFinalizeto (C#) lub Me (Visual Basic).
Jeśli typ nie ma zostać zastąpiony, oznacz go jako
sealed.
Kiedy pomijać ostrzeżenia
Tylko pomijaj ostrzeżenie z tej reguły, jeśli celowo używasz GC.SuppressFinalize do kontrolowania okresu istnienia innych obiektów. Nie pomijaj ostrzeżenia tej reguły, jeśli implementacja Dispose nie wywołuje GC.SuppressFinalize. W takiej sytuacji niedopilnowanie usunięcia finalizacji obniża wydajność i nie zapewnia żadnych korzyści.
Pomijanie ostrzeżenia
Jeśli chcesz po prostu pominąć pojedyncze naruszenie, dodaj dyrektywy preprocesora do pliku źródłowego, aby wyłączyć, a następnie ponownie włączyć regułę.
#pragma warning disable CA1816
// The code that's violating the rule is on this line.
#pragma warning restore CA1816
Aby wyłączyć regułę dla pliku, folderu lub projektu, ustaw jego ważność na none w pliku konfiguracji.
[*.{cs,vb}]
dotnet_diagnostic.CA1816.severity = none
Aby uzyskać więcej informacji, zobacz Jak pominąć ostrzeżenia dotyczące analizy kodu.
Przykład naruszający CA1816
Ten kod przedstawia metodę, która wywołuje GC.SuppressFinalize, ale nie przekazuje ani this (C#) lub Me (Visual Basic). W związku z tym ten kod narusza regułę CA1816.
Public Class MyStreamClass
Implements IDisposable
Private _stream As New MemoryStream
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
' Violates rule.
GC.SuppressFinalize(True)
End Sub
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If _stream IsNot Nothing Then
_stream.Dispose()
_stream = Nothing
End If
End If
End Sub
End Class
public class MyStreamClass : IDisposable
{
private MemoryStream? _stream = new();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(true); // Violates rule
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_stream?.Dispose();
_stream = null;
}
}
}
Przykład spełniający wymagania ca1816
W tym przykładzie pokazano metodę, która poprawnie wywołuje GC.SuppressFinalize, przekazując this (C#) lub Me (Visual Basic).
Public Class MyStreamClass
Implements IDisposable
Private _stream As New MemoryStream
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(Me)
End Sub
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If _stream IsNot Nothing Then
_stream.Dispose()
_stream = Nothing
End If
End If
End Sub
End Class
public class MyStreamClass : IDisposable
{
private MemoryStream? _stream = new();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
_stream?.Dispose();
_stream = null;
}
}
}
Powiązane reguły
- CA2215: Metody Dispose powinny wywoływać metodę Dispose klasy podstawowej
- CA2216: Typy możliwe do likwidacji powinny deklarować finalizator