CA1816:正確呼叫 GC.SuppressFinalize
型別名稱 |
CallGCSuppressFinalizeCorrectly |
CheckId |
CA1816 |
分類 |
Microsoft。使用方式 |
中斷變更 |
不中斷 |
原因
屬於 IDisposable.Dispose 實作的方法不會呼叫 GC.SuppressFinalize。
不屬於 IDisposable.Dispose 實作的方法會呼叫 GC.SuppressFinalize。
呼叫 GC.SuppressFinalize,並傳遞不同於 this (在 Visual Basic 中為 Me) 之值的方法。
規則描述
在物件可讓記憶體回收之前,IDisposable.Dispose 方法讓使用者可以隨時釋放資源。如果呼叫 IDisposable.Dispose 方法,則會釋放物件的資源。這使得不需要最終處理。IDisposable.Dispose 應該呼叫 GC.SuppressFinalize,以便讓記憶體回收行程不會呼叫物件的完成項。
若要避免使用完成項的衍生類別需要重新實作 [System.IDisposable] 以及呼叫它,未使用完成項的非密封型別仍應該呼叫 GC.SuppressFinalize。
如何修正違規
若要修正此規則的違規情形:
如果方法是 Dispose 的實作,請將呼叫加入至 GC.SuppressFinalize。
如果方法不是 Dispose 的實作,請移除對 GC.SuppressFinalize 的呼叫,或將其移至型別的 Dispose 實作。
變更 GC.SuppressFinalize 的所有呼叫以傳遞 this (Visual Basic 中的 Me)。
隱藏警告的時機
只有在考慮使用 GC.SuppressFinalize 控制其他物件的存留期時,才隱藏這項規則的警告。如果 Dispose 的實作並未呼叫 GC.SuppressFinalize,請勿隱藏這項規則的警告。在這種情況下,無法隱藏最終化將會降低效能且不提供任何好處。
範例
下列範例會示範不正確呼叫 GC.SuppressFinalize 的方法。
Imports System
Imports System.Data.SqlClient
Namespace Samples
Public Class DatabaseConnector
Implements IDisposable
Private _Connection As New SqlConnection
Public Sub Dispose() Implements IDisposable.Dispose
Dispose(True)
GC.SuppressFinalize(True) ' Violates rules
End Sub
Protected Overridable Sub Dispose(ByVal disposing As Boolean)
If disposing Then
If _Connection IsNot Nothing Then
_Connection.Dispose()
_Connection = Nothing
End If
End If
End Sub
End Class
End Namespace
using System;
using System.Data.SqlClient;
namespace Samples
{
public class DatabaseConnector : IDisposable
{
private SqlConnection _Connection = new SqlConnection();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(true); // Violates rule
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_Connection != null)
{
_Connection.Dispose();
_Connection = null;
}
}
}
}
}
下列範例示範以正確方式呼叫 GC.SuppressFinalize 的方法。
Imports System
Imports System.Data.SqlClient
Namespace Samples
Public Class DatabaseConnector
Implements IDisposable
Private _Connection As New SqlConnection
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 _Connection IsNot Nothing Then
_Connection.Dispose()
_Connection = Nothing
End If
End If
End Sub
End Class
End Namespace
using System;
using System.Data.SqlClient;
namespace Samples
{
public class DatabaseConnector : IDisposable
{
private SqlConnection _Connection = new SqlConnection();
public void Dispose()
{
Dispose(true);
GC.SuppressFinalize(this);
}
protected virtual void Dispose(bool disposing)
{
if (disposing)
{
if (_Connection != null)
{
_Connection.Dispose();
_Connection = null;
}
}
}
}
}