MORE INFORMATION
The existing documentation should also include the following
information:
You can also use the
KeepAlive method to prevent a finalizer from being started prematurely. The
following scenario describes the problem that may occur if you do not prevent a
finalizer from being started prematurely:
- You have an object that is a member of a class. You work
with this object in the finalizer of the class, and then you instantiate a
different object of the class.
- You try to gain access to an object that is a member of the
newly instantiated object.
In this scenario, you may notice that the newly instantiated
object is prematurely finalized. Therefore, the object that is a member of the
newly instantiated object is manipulated in the finalizer. This behavior may
cause unexpected results.
To prevent the finalizer from being started
prematurely, start the
KeepAlive method and use a reference to the newly instantiated object as
the parameter. Start the
KeepAlive method in the method or property procedure where you gain access
to the object that is a member of the newly instantiated object. To do this,
use the following sample code:
Microsoft Visual Basic .NET sample code
Option Strict On
Imports System
Namespace KeepAliveDemo
Class Class1
' Object that is a member of a class.
Private MyPrivateArray As Integer()
Public ReadOnly Property MyArray() As Integer()
Get
Return CType(MyPrivateArray.Clone(), Integer())
End Get
End Property
' Constructor.
Public Sub New()
MyPrivateArray = New Integer(5) {}
MyPrivateArray(0) = 10
End Sub
' Finalizer.
Protected Overrides Sub Finalize()
MyBase.Finalize()
If Not (MyPrivateArray Is Nothing) Then
' Modify the object that is a member of this class.
Array.Clear(MyPrivateArray, 0, MyPrivateArray.Length)
End If
End Sub
End Class
Class Class2
Shared Sub Main()
Dim Continue As Boolean = True
While (Continue)
' Instantiate an object of type Class1.
Dim Test As New Class1
If Test.MyArray(0) = 10 Then
Console.WriteLine("Finalizer not invoked prematurely")
Else
Console.WriteLine("Finalizer invoked prematurely. Press ENTER to quit.")
Console.ReadLine()
Continue = False
End If
' If the following statement is missing, the finalizer may be invoked prematurely.
GC.KeepAlive(Test)
End While
End Sub
End Class
End Namespace
Microsoft Visual C# .NET sample code
using System;
namespace KeepAliveDemo
{
class Class1
{
// Object that is a member of a class.
private int[] MyPrivateArray;
public int[] MyArray
{
get
{
return (int[]) MyPrivateArray.Clone();
}
}
// Constructor.
public Class1()
{
MyPrivateArray = new int[5];
MyPrivateArray[0] = 10;
}
// Finalizer.
~Class1()
{
if (MyPrivateArray != null)
// Modify the object that is a member of this class.
Array.Clear(MyPrivateArray, 0, MyPrivateArray.Length);
}
}
class Class2
{
static void Main(string[] args)
{
bool Continue = true;
while(Continue)
{
// Instantiate an object of type Class1.
Class1 Test = new Class1();
if (Test.MyArray[0] == 10)
Console.WriteLine("Finalizer not invoked prematurely");
else
{
Console.WriteLine("Finalizer invoked prematurely; press ENTER to quit");
Console.ReadLine();
Continue = false;
}
// If the following statement is missing, the finalizer may be invoked prematurely.
GC.KeepAlive(Test);
}
}
}
}
In this example,
MyPrivateArray is a member of
Class1.
MyPrivateArray is manipulated in the finalizer of
Class1.
Test is an object of type Class1.
Test is instantiated in the
Main method of
Class2, and the corresponding
MyPrivateArray member is accessed by using the
MyArray property. If you do not use
GC.KeepAlive(Test) when you run this sample application, you may receive the
following custom message:Finalizer invoked prematurely;
press ENTER to quitThis message indicates that
Test was prematurely finalized.
Also, use the
KeepAlive method when you work with member data in the
Dispose method of classes that inherit from the IDisposable interface.
The implementation details are similar to the previous
example.
Microsoft recommends that you always use write code similar
to the example that appears in this article when you work with object
references (other than a reference to the current object) in finalizers or in
Dispose methods.