Microsoft KB Archive/821779

= Help topic for the GC.KeepAlive method is not complete =

Article ID: 821779

Article Last Modified on 5/16/2007

-

APPLIES TO


 * Microsoft Visual Studio .NET 2003 Enterprise Architect
 * Microsoft Visual Studio .NET 2003 Enterprise Developer
 * Microsoft Visual Studio .NET 2003 Academic Edition
 * Microsoft Visual Studio .NET 2002 Professional Edition
 * Microsoft Visual Studio .NET 2002 Enterprise Architect
 * Microsoft Visual Studio .NET 2002 Enterprise Developer
 * Microsoft Visual Studio .NET 2002 Academic Edition

-



SUMMARY
In the Microsoft .NET Framework Class Library documentation, the Help topic for the GC.KeepAlive method is not complete. For more information, visit the following Microsoft Web site:

http://msdn2.microsoft.com/en-us/library/system.gc.keepalive(vs.71).aspx



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:
 * 1) 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.
 * 2) 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(&quot;Finalizer not invoked prematurely&quot;) Else Console.WriteLine(&quot;Finalizer invoked prematurely. Press ENTER to quit.&quot;) 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(&quot;Finalizer not invoked prematurely&quot;); else {                   Console.WriteLine(&quot;Finalizer invoked prematurely; press ENTER to quit&quot;); 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 quit

This 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.

