.NET Matters

Finalizers, Assembly Names, MethodInfo, and More

Stephen Toub

Code download available at:NETMatters0405.exe(139 KB)

Q When do I need to implement a finalizer on my class? Should I always do it, or only when I'm holding onto unmanaged resources? Should I always implement the IDisposable interface when I have a finalizer, and vice versa?

Q When do I need to implement a finalizer on my class? Should I always do it, or only when I'm holding onto unmanaged resources? Should I always implement the IDisposable interface when I have a finalizer, and vice versa?

A Finalizers only need to be implemented when you hold onto resources that need cleaning up. For example, FileStream holds onto a native file handle and implements a finalizer so as to release the handle when the FileStream is garbage collected. Unfortunately, finalizers place a significant amount of pressure on the garbage collector and should be used only when absolutely needed.

A Finalizers only need to be implemented when you hold onto resources that need cleaning up. For example, FileStream holds onto a native file handle and implements a finalizer so as to release the handle when the FileStream is garbage collected. Unfortunately, finalizers place a significant amount of pressure on the garbage collector and should be used only when absolutely needed.

The IDisposable interface announces to the world that your class holds onto resources that need to be disposed and allows users of your class to deterministically release them. Therefore, any class that implements a finalizer should also implement IDisposable (if the garbage collector can free resources, a developer should be allowed to do it explicitly). However, the opposite is not necessarily true; not all classes that implement IDisposable need to or even should implement a finalizer.

Consider the scenario where my managed class has a FileStream as a private member. FileStream holds onto unmanaged resources and implements both IDisposable and a finalizer. When no more references to the instance exist, this FileStream will be similarly unreachable and will be available for finalization. There's no reason for my class to be in the queue of objects that have registered for finalization since the instance of FileStream will be there. But my class should provide a way for a user to immediately release all resources it holds onto, either directly or indirectly, and therefore my class should implement IDisposable. My implementation of Dispose will simply call the FileStream's Dispose method. Note, though, that you need to be careful not to dispose of shared resources (resources used by other instances, for example). If you write a class that will dispose of a resource made available to it from an external source, make sure your documentation is clear on the subject so that others know whether they're handing over control of any resources they give you.

If you do need to implement a finalizer in your class, your Dispose method should use the GC.SuppressFinalize method to ensure that finalization of your instance is suppressed. This will remove the instance from the set of objects that require finalization, reducing the pressure on the garbage collector during a collection. A common pattern implemented throughout the Microsoft® .NET Framework is to add to a class a Dispose method that takes a Boolean as a parameter. This Boolean indicates whether the class is being disposed because the IDisposable.Dispose method is called or because the finalizer is run (both the finalizer and IDisposable.Dispose delegate to this method). If it's being disposed deterministically, GC.SuppressFinalize is invoked. If it's being called from a finalizer, avoid using managed members of your class that implement finalizers as they may have already been finalized.

Figure 1 provides guidelines on when it is appropriate to implement these constructs in your classes.

Figure 1 When to Implement IDisposable and/or a Finalizer

Your Class Holds Onto IDisposable Finalizer
Only managed resources that don't implement IDisposable or have any way of being closed    
Only managed resources, but some of them implement IDisposable or can be closed in some way  
Both managed resources and unmanaged resources
Only unmanaged resources

Q I'd like to base some operations that my application performs on the amount of memory available in the computer. What's the easiest way to ask the operating system for this information?

Q I'd like to base some operations that my application performs on the amount of memory available in the computer. What's the easiest way to ask the operating system for this information?

A While I'm sure there are other ways to obtain this information, I've found Windows® Management Instrumentation (WMI) to be perfect for these types of tasks. The Win32_OperatingSystem class provides a wealth of information about the happenings of the OS, and the System.Management namespace provides a very nice set of classes to access WMI data. You can use the ManagementObjectSearcher class as shown in Figure 2 to query for Win32_OperatingSystem.TotalVisibleMemorySize. Since ManagementObjectCollection (as returned by ManagementObjectSearcher) does not expose a method to access individual items in the collection, I've used a foreach loop to access its contents through an enumerator. I only care about one value, so I stop after the first iteration.

A While I'm sure there are other ways to obtain this information, I've found Windows® Management Instrumentation (WMI) to be perfect for these types of tasks. The Win32_OperatingSystem class provides a wealth of information about the happenings of the OS, and the System.Management namespace provides a very nice set of classes to access WMI data. You can use the ManagementObjectSearcher class as shown in Figure 2 to query for Win32_OperatingSystem.TotalVisibleMemorySize. Since ManagementObjectCollection (as returned by ManagementObjectSearcher) does not expose a method to access individual items in the collection, I've used a foreach loop to access its contents through an enumerator. I only care about one value, so I stop after the first iteration.

Figure 2 Using WMI from .NET

private static ulong PhysicalMemory { get { SelectQuery query = new SelectQuery("Win32_OperatingSystem"); using (ManagementObjectSearcher searcher = new ManagementObjectSearcher(query)) { foreach(ManagementObject mo in searcher.Get()) { ulong memAvailable; try { memAvailable = (ulong)mo["TotalVisibleMemorySize"]; } finally { mo.Dispose(); } return memAvailable; } } throw new InvalidOperationException( "Couldn't get physical memory size."); } }

Note that the value reported by TotalVisibleMemorySize might not be the total amount of physical memory in the computer, but rather what is reported to the OS as being available to it. You can learn more about the information available through the Win32_OperatingSystem WMI class at Win32_OperatingSystem.

Q I'm trying to get the strong name of an assembly without loading the assembly into my AppDomain. Is this possible?

Q I'm trying to get the strong name of an assembly without loading the assembly into my AppDomain. Is this possible?

A Absolutely. The System.Reflection.AssemblyName class has a static method, GetAssemblyName, that can be used to retrieve the AssemblyName for an assembly on disk. This method will briefly open the assembly file, but the assembly will not be loaded into the AppDomain. The following code will write out to the console the name of an assembly whose path is specified as a command-line argument, as shown here:

static void Main(string [] args) { if (args.Length > 0) { try { AssemblyName a = AssemblyName.GetAssemblyName(args[0]); Console.WriteLine(a.Fullname); } catch(Exception exc) { Console.WriteLine(exc.Message); } } }

A Absolutely. The System.Reflection.AssemblyName class has a static method, GetAssemblyName, that can be used to retrieve the AssemblyName for an assembly on disk. This method will briefly open the assembly file, but the assembly will not be loaded into the AppDomain. The following code will write out to the console the name of an assembly whose path is specified as a command-line argument, as shown here:

static void Main(string [] args) { if (args.Length > 0) { try { AssemblyName a = AssemblyName.GetAssemblyName(args[0]); Console.WriteLine(a.Fullname); } catch(Exception exc) { Console.WriteLine(exc.Message); } } }

Note that this same technique can be used to determine which DLLs and EXEs are native and which are managed. You can loop over all of the files to be tested and query for their AssemblyName. If no exception is thrown and you get back a valid name, the file is managed. However, this does have some performance drawbacks as all native files will cause exceptions to be thrown. Another way doesn't rely on reflection and doesn't attempt to load the Portable Executable (PE). Rather, it parses the PE header of the DLL or EXE in order to determine if the appropriate bits are set demarking the DLL as managed. The FAQ at Managed Extensions for C++ Frequently Asked Questions provides C++ code to do this. Equivalent C# code is shown in Figure 3.

Figure 3 Determining if a Portable Executable is Managed

private static bool IsManaged(string fileName) { byte [] data = new byte[4096]; using (FileStream file = new FileStream(fileName, FileMode.Open, FileAccess.Read)) { file.Read(data, 0, data.Length); } if ((data[1] << 8 | data[0]) != 0x5a4d) return false; int winNtHdr = data[63]<<24 | data[62]<<16 | data[61]<<8 | data[60]; if ((data[winNtHdr+3]<<24 | data[winNtHdr+2]<<16 | data[winNtHdr+1]<<8 | data[winNtHdr]) != 0x4550) return false; int lightningAddr = winNtHdr + 24 + 208, sum=0, top=lightningAddr+8; for(int i=lightningAddr; i<top; i++) sum |= data[i]; return sum != 0; }

Q I have a bunch of foreach loops in my C# application. When I look at the compiler-generated Microsoft intermediate language (MSIL), I see that some include a try/finally block, but I didn't have any in my original code. Why were these added?

Q I have a bunch of foreach loops in my C# application. When I look at the compiler-generated Microsoft intermediate language (MSIL), I see that some include a try/finally block, but I didn't have any in my original code. Why were these added?

A Good question. Remember that a foreach loop is used to iterate over collection types. This is accomplished by retrieving an enumerator and using its MoveNext operation to continually walk the list and its Current property to retrieve the current item from the list. The enumerator is retrieved using the collection's GetEnumerator method. Since this enumerator might implement IDisposable, the C# compiler needs to ensure that it is disposed as soon as the iteration has completed. As a result, it generates the loop in a try block and then attempts to dispose of the enumerator in the finally block. If the return type of the GetEnumerator method is one that implements IDisposable, the compiler will generate a finally block containing code similar to this:

((IDisposable)enumerator).Dispose();

A Good question. Remember that a foreach loop is used to iterate over collection types. This is accomplished by retrieving an enumerator and using its MoveNext operation to continually walk the list and its Current property to retrieve the current item from the list. The enumerator is retrieved using the collection's GetEnumerator method. Since this enumerator might implement IDisposable, the C# compiler needs to ensure that it is disposed as soon as the iteration has completed. As a result, it generates the loop in a try block and then attempts to dispose of the enumerator in the finally block. If the return type of the GetEnumerator method is one that implements IDisposable, the compiler will generate a finally block containing code similar to this:

((IDisposable)enumerator).Dispose();

However, if the enumerator type returned does not implement IDisposable, the compiler still has to attempt to dispose the object since it can't be sure that a derived type (which can be returned from the function) doesn't implement IDisposable. Consequently, the compiler will generate a finally block containing several lines of code similar to the following:

IDisposable disposable = enumerator as IDisposable; if (disposable != null) disposable.Dispose();

Since most enumerable classes have a GetEnumerator method that returns IEnumerator (which does not implement IDisposable), the previous code is the most commonly generated. In the rare case where the return type does not implement IDisposable and is sealed (meaning that no types are derived from the return type), the compiler doesn't need to implement a try/finally since there is nothing to be disposed.

Q I want to enumerate all of the objects in an object hierarchy, but there's a good chance there are cyclical references and I'm not sure how to avoid them. Does the .NET Framework provide anything to help me out in this situation?

Q I want to enumerate all of the objects in an object hierarchy, but there's a good chance there are cyclical references and I'm not sure how to avoid them. Does the .NET Framework provide anything to help me out in this situation?

A Iterating over all of the objects in an object hierarchy and serializing them out in some fashion is exactly what the remoting formatters like BinaryFormatter do. As a result, there are some helpful classes in the Framework that make this task simple. The ObjectIDGenerator class in the System.Runtime.Serialization namespace is a specialized table that's able to keep track of objects and unique identifiers for them. You can ask it for the ID of an object, and it will either give you the existing ID for an object it's already seen or generate a new ID for an unseen object. This makes it very easy to avoid cycles because it prevents you from iterating over the same object twice. In addition, the collection classes in the System.Collections namespace make it easy to track objects that still need to be examined.

A Iterating over all of the objects in an object hierarchy and serializing them out in some fashion is exactly what the remoting formatters like BinaryFormatter do. As a result, there are some helpful classes in the Framework that make this task simple. The ObjectIDGenerator class in the System.Runtime.Serialization namespace is a specialized table that's able to keep track of objects and unique identifiers for them. You can ask it for the ID of an object, and it will either give you the existing ID for an object it's already seen or generate a new ID for an unseen object. This makes it very easy to avoid cycles because it prevents you from iterating over the same object twice. In addition, the collection classes in the System.Collections namespace make it easy to track objects that still need to be examined.

The code in Figure 4 implements my solution. The ObjectWalker class provides an implementation for an IEnumerator that makes it easy to walk the entire object hierarchy using a foreach loop to enumerate all of the objects:

foreach(object obj in new ObjectWalker(hierarchy)) { Console.WriteLine("{0}:\t{1}", obj.GetType(), obj); }

Figure 4 Enumerating an Object Hierarchy

public class ObjectWalker : IEnumerable, IEnumerator { private object _obj, _current; private Stack _toWalk; private ObjectIDGenerator _idGen; public ObjectWalker(object obj) { if (obj == null) throw new ArgumentNullException("obj"); _obj = obj; Reset(); } public IEnumerator GetEnumerator() { return this; } public void Reset() { _toWalk = new Stack(); _idGen = new ObjectIDGenerator(); Schedule(_obj); } public object Current { get { return _current; } } private void Schedule(object toSchedule) { if (toSchedule == null) return; bool firstOccurrence; _idGen.GetId(toSchedule, out firstOccurrence); if (firstOccurrence) { if (toSchedule.GetType().IsArray) { foreach(object arrItem in ((Array)toSchedule)) Schedule(arrItem); } else _toWalk.Push(toSchedule); } } public bool MoveNext() { if (_toWalk.Count == 0) return false; if (!IsTerminalObject(_current = _toWalk.Pop())) { foreach(FieldInfo fi in _current.GetType().GetFields( BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic)) { object toSchedule = fi.GetValue(_current); if (toSchedule != null) Schedule(toSchedule); } } return true; } private bool IsTerminalObject(object data) { Type t = data.GetType(); return t.IsPrimitive || t.IsEnum || t.IsPointer || data is string; } }

Iteration begins by pushing the root object onto a stack. Each time MoveNext is called, the code pops an object from the stack and stores it as the next value to be returned from the Current property. In addition, it uses reflection to determine whether there are any fields on the object that need to be enumerated. If there are, it grabs all valid objects from those fields and uses the ObjectIDGenerator to determine if they've already been processed. If they haven't, they're added to the processing stack for future retrieval. Before checking for fields, however, the code first checks to see if the current object represents a termination condition. For this implementation, I stop recurring when a primitive (such as int or byte), a string, an enum, or a pointer is found. I stop on pointers so that I don't attempt to dig around in unmanaged memory.

As the MoveNext method uses reflection to access the contents of potentially non-public fields, this class requires the appropriate ReflectionPermission to operate successfully.

Q In my GUI application, I have a MethodInfo object that represents a method that modifies a control on my main form. This MethodInfo is obtained by another piece of the system using reflection and can represent methods with a wide variety of signatures. As this code is running on a worker thread, I need to use the control's Invoke method to execute the specified method on the thread that owns the control's underlying window handle, but to do so requires a delegate for the method I want executed. How can I convert my MethodInfo object to a delegate so that I can pass it to the Invoke method?

Q In my GUI application, I have a MethodInfo object that represents a method that modifies a control on my main form. This MethodInfo is obtained by another piece of the system using reflection and can represent methods with a wide variety of signatures. As this code is running on a worker thread, I need to use the control's Invoke method to execute the specified method on the thread that owns the control's underlying window handle, but to do so requires a delegate for the method I want executed. How can I convert my MethodInfo object to a delegate so that I can pass it to the Invoke method?

A If you already have a delegate class whose signature matches that of the method represented by the MethodInfo, and if that method is static, then the static Delegate.CreateDelegate method will do exactly what you need. Pass it the Type object for the delegate to instantiate and the MethodInfo for the static method to wrap, and it'll return to you an appropriate delegate instance. This delegate can then be passed to the Invoke method of the control, as shown in the following lines of code:

MyDelegate d = (MyDelegate)Delegate.CreateDelegate( typeof(MyDelegate), theMethodInfo); theControl.Invoke(d, new object[]{param1, param2, ...});

A If you already have a delegate class whose signature matches that of the method represented by the MethodInfo, and if that method is static, then the static Delegate.CreateDelegate method will do exactly what you need. Pass it the Type object for the delegate to instantiate and the MethodInfo for the static method to wrap, and it'll return to you an appropriate delegate instance. This delegate can then be passed to the Invoke method of the control, as shown in the following lines of code:

MyDelegate d = (MyDelegate)Delegate.CreateDelegate( typeof(MyDelegate), theMethodInfo); theControl.Invoke(d, new object[]{param1, param2, ...});

If the method is not static, you can use a different overload of Delegate.CreateDelegate that takes the delegate type as before, along with the name of the method and the instance of the object on which the method should be invoked:

MyDelegate d = (MyDelegate)Delegate.CreateDelegate( typeof(MyDelegate), targetObj, theMethodInfo.Name); theControl.Invoke(d, new object[]{param1, param2, ...});

However, since this still requires a delegate for the MethodInfo signature and since you may not have the correct delegate type on hand, this will not work for all scenarios. A better solution is to create a delegate class that can work for any MethodInfo. To do this, you can create a delegate whose signature matches that of MethodInfo.Invoke, which takes the target instance as the first argument (or null for static methods), and the parameters for the call in an object array as the second argument. The delegate declaration can be written as follows:

private delegate object MethodInvokeHandler( object target, object [] parameters);

You can then create an instance of this delegate that wraps your MethodInfo's Invoke method and pass that delegate to the Control's Invoke method, as shown here:

MethodInvokeHandler d = new MethodInvokeHandler(theMethodInfo.Invoke); object [] parameters = new object[]{param1, param2, ...}; theControl.Invoke(d, new object[]{targetObj, parameters});

Using this approach and the delegate defined previously, you can get Control.Invoke to invoke any method for which you have a MethodInfo object.

Another solution is to dynamically generate a delegate class that works with methods that have the matching signature (Paul DiLascia and Dino Esposito discuss code generation in their columns this month). You can then use the Delegate.CreateDelegate method as described previously. Why would you want to dynamically generate a delegate when you have the solution just presented? Because the solution given is relatively slow. Rather than being able to call to the method directly (a delegate is, in a sense, an object-oriented function pointer and is efficient, although it's still much more expensive than directly calling a method), the solution has you invoking a delegate that executes an invocation that does a late-bound call to the actual method.

While dynamically generating code can incur a performance penalty, you only have to do it once up front and from then on you get the speed benefits on every call. If you'll be making many calls, it's worth the startup time you spend. In my testing where the target method performed simple arithmetic on integer arguments, using the dynamically generated delegate improved performance more than five fold. Of course, this argument is moot if the target method does any kind of real work. The overhead involved in making the call could be insignificant compared to the time taken in the method, in which case simplicity is best.

As you should do with most software projects, write the code first so that it's clean and it works. Then if it does not perform up to par, use a profiler to determine the hotspots and fix those until performance is adequate.

Q What algorithm is used by the System.Random class? Is the algorithm cryptographically secure?

Q What algorithm is used by the System.Random class? Is the algorithm cryptographically secure?

A In current versions of the .NET Framework, System.Random uses an algorithm based on the subtractive method described by Donald Knuth in The Art of Computer Programming, Volume 2: Seminumerical Algorithms (Addison-Wesley, 1997). You can see the source for the System.Random class in the Shared Source Common Language Infrastructure (SSCLI), available online at System.Random Class.

A In current versions of the .NET Framework, System.Random uses an algorithm based on the subtractive method described by Donald Knuth in The Art of Computer Programming, Volume 2: Seminumerical Algorithms (Addison-Wesley, 1997). You can see the source for the System.Random class in the Shared Source Common Language Infrastructure (SSCLI), available online at System.Random Class.

System.Random is not cryptographically secure and should not be used for any applications where predictability can pose a threat. The RNGCryptoServiceProvider class in the System.Security.Cryptography namespace is, however, a cryptographically secure random number generator and can be used in situations where cryptographically strong random values are required.

Q In last month's column you answered a question on how to obtain the path to the common language runtime (CLR) installation directory. You used P/Invoke to access the unmanaged GetCORSystemDirectory function exposed from mscoree.dll. Why did you choose that approach as opposed to the other ones that are available to you?

Q In last month's column you answered a question on how to obtain the path to the common language runtime (CLR) installation directory. You used P/Invoke to access the unmanaged GetCORSystemDirectory function exposed from mscoree.dll. Why did you choose that approach as opposed to the other ones that are available to you?

A There are two other simple ways that I know of to get at the same directory path. The first, and easiest, is the GetRuntimeDirectory method on the System.Runtime.InteropServices.RuntimeEnvironment class. The second way is to get the type of a class that lives in mscorlib.dll (such as the object class) and then use that Type object to get the fully qualified name of the mscorlib module. On a machine running Windows XP with version 1.1 of the .NET Framework, this resolves to %windir%\microsoft.net\framework\v1.1.4322\mscorlib.dll. The System.IO.Directory.GetParent method can then be used to get the path of the parent folder.

A There are two other simple ways that I know of to get at the same directory path. The first, and easiest, is the GetRuntimeDirectory method on the System.Runtime.InteropServices.RuntimeEnvironment class. The second way is to get the type of a class that lives in mscorlib.dll (such as the object class) and then use that Type object to get the fully qualified name of the mscorlib module. On a machine running Windows XP with version 1.1 of the .NET Framework, this resolves to %windir%\microsoft.net\framework\v1.1.4322\mscorlib.dll. The System.IO.Directory.GetParent method can then be used to get the path of the parent folder.

While the RuntimeEnvironment.GetRuntimeDirectory method is certainly the easiest to use, it is not the fastest. Tests on my machine show this method to perform approximately 5 times slower than the equivalent interop approach, and the type approach to perform approximately 15 times slower. Of course, there's no need for any of these functions to be called in a long-running tight loop and, as such, efficiency isn't a huge issue. But the speed of the interop option coupled with the fact that interop is just really cool made me want to show that approach.

Send your questions and comments to  netqa@microsoft.com.

Stephen Toub is the Technical Editor for MSDN Magazine.