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;
}
}
}
}
}