Debug vs Release mode differences when storing a delegate in a hashtable

The following code demonstrates a difference in the behavior of the .NET runtime between debug and release mode.  I'm running .NET 1.1 with SP1 on Server 2003, but this also happens on Win2k and XP.  We've been seeing it for months, but it was finally isolated by a team in Samara.

The code demonstrates three ways to test if a delegate is stored in the hashtable.  All work in debug mode, but the first fails in Release mode unless the Release mode code is running under a debugger. 

Does anyone have experience with this problem?  Or know if a fix is available already or coming in 2.0?

using System;

using System.Collections;

 

namespace DelegatesBug

{

      /// <summary>

      /// Illustrates a difference in the Release and Debug mode behavior of delegates that are

      /// contained in a hashtable. 

      /// Creates a delegate around a method and adds the delegate to a hashtable. 

      /// At that point, asking the hashtable if it contains a new delegate around the same

      /// method returns true in debug mode and false in release mode.  Running the release

      /// mode in the debugger returns true (the same result as in debug mode)

      /// </summary>

      class DelegatesBug

      {          

            [STAThread]

            static void Main(string[] args)

            {

                  Test test = new Test();

                  Hashtable hashtable = new Hashtable();

                  TestDelegate td = new TestDelegate(test.Method);

                  hashtable.Add(td, null);

 

                  td(); // if this call is commented out, release and debug modes work the same

 

                  // the Contains call returns false in release mode with no debugger (Ctrl + F5). With

                  // debug mode or the debugger enabled, it returns true.

                  Console.WriteLine("New delegate is contained in hashtable: " + hashtable.Contains(new TestDelegate(test.Method)));

 

                  // comparing the two delegates returns true

                  foreach (MulticastDelegate del in hashtable.Keys)

                        Console.WriteLine("The delegate from hashtable.Keys equals td: " + del.Equals(td));

 

                  // asking the hashtable if it contains the original delegate returns true

                  Console.WriteLine("td is contained in the hashtable: " + hashtable.Contains(td));

                  Console.ReadLine();               

            }

      }

 

      public delegate void TestDelegate();

      public class Test

      {

            public void Method()

            {          

            }

      }

}

 

Published 14 April 2005 05:11 PM by Ted_Graham

Comments

# Wesner Moise said on 14 April, 2005 08:39 PM
This looks like the difference between a function's address before it is jitted and after. The first delegate may actually point to a stub routine in release mode.

I doubt it has anything to do with the optimizations that occur in Release mode.

I suspect that NGEN'd code will produce a true result as well.
# UdiDahan@TheSoftwareSimplist.com (Udi Dahan - The said on 15 April, 2005 03:21 AM
While 2 delegate objects that reference the same method on the same object may be equivalent (calling the first delegate results in the same behavior as calling the second), I would not say that they are equal.
# MyName said on 25 October, 2007 10:59 AM

Il est pourri ton code, c'est normal qu'il y ait des bugs après faut pas s'étonner...

# Jayesh said on 20 June, 2008 12:34 PM

This seems to be resolved in .NET 2.0+ as it returns TRUE in all the cases now.

# fgf said on 24 September, 2008 04:48 AM

hgjgjuhjgggh

hgj

ghjhg

Leave a Comment

(required) 
(required) 
(optional)
(required)