March 2006 - Posts

IKeyComparer?

The preperation guide for 70-536 Microsoft .NET Framework 2.0 - Application Development Foundation points to the IKeyComparer and the IHashCodeProvider interfaces as fundamentals you should be proficient with before taking the test. There is no such thing as an IKeyComparer interface in the .NET Framework 2.0 - the interface was removed after beta 1. The IHashCodeProvider interface has been marked obsolete in .NET 2.0 and you should use the IEqualityComparer interface instead.

The beta 1 design of the IComparer interface grouped all comparison related methods into a single interface to avoid a common design fault from .NET 1.1, where one could pass an incompatible pair of IComparer and IHashCodeProvider to the Hashtable constructor. After shipping beta 1 of .NET 2.0, Microsoft split their original IComparer interface into the IEqualityComparer and a new definition of IComparer after realizing that the new design introduced incompatabilies with classes that currently didn’t implent IComparable and that the IComparable.CompareTo(T) method required types to have natural ordering.

The IKeyComparer was in essence both an IHashCodeProvider and an IComparer that was intended to be used to compare dictionary keys based on hashcode equality, thus avoiding the .NET 1.1 scenario where one could pass an IHashCodeProvider that considered two instances equal along with an IComparer that considered the same instances as inequal making the Hashtable indexer fail to find a value with a given key.
You might also have heard of an interface called IHashComparer. This was a proposed name for the IKeyComparer interface during the beta 2 refactoring, but this interface was not included in the final release of .NET 2.0.

The one interface you should know is IEqualityComparer. This is a special interface that should only be used for determining equality, and not for sorting. The interface is particularly handy for culture aware comparisons such as determing that the German words ”weiss” and ”weiß” are the same.

How To: Strongname Inheritance Demands at Runtime

Yesterday a client of mine had an interesting challenge. He had a sealed class which he needed to “unseal” due to some changes in his project. However he needed to control who could inherit the class and applied a StrongNameIdentityPermissionAttribute with an InheritanceDemand action to the class. He soon learned that the XmlSerializer cannot serialize types with declarative security. This is by design in the .NET framework, since XML serialization is achieved through runtime generated types for performance reasons. A common workaround is to apply imperative security in lieu of declarative security. However, since InheritanceDemand is a load time security assertion, this was not a feasible option for my client.
The solution to the challenge was to recreate the inheritance demand action in the class’ constructor as shown below.
public abstract class InheritanceDemandingClass
{
    protected InheritanceDemandingClass()
    {
        byte[] myPK = typeof(InheritanceDemandingClass).Assembly.GetName().GetPublicKey();
        byte[] callingPK = Assembly.GetCallingAssembly().GetName().GetPublicKey ();
        if (callingPK==null || myPK.Length!=callingPK.Length)
        {
            throw new SecurityException("The calling assembly does not have permission to create this type.");
        }
        for (int i = 0; i < myPK.Length; i++)
        {
            if (myPK[i]!=callingPK[i])
            {
                throw new SecurityException("The calling assembly does not have permission to create this type.");                 
            }
        }
    }
}

The above code compares the calling assembly’s public key with the class’ public key and throws a SecurityException if the two assemblies aren’t signed with the same key. This simple solution should be sufficient for most scenarios, as the common usage for inheritance demands is to ensure that only your types can extend your types. However the example can easily be extended to support other keys or public key tokens as well.
There are some differences with this approach and using declarative security; the type can be reflected since the security assertion happens at runtime, and you cannot use permview.exe to see what demands the type makes. If imperative security was applied you would still have both of these issues.

Heisenbugs and Conditional Breakpoints

Have you ever heard the term Heisenbug? If not, it is adopted from Heisenberg’s Uncertainty Principle in quantum physics. An Heisenbug is a bug that disappears or alters its behavior when one tries to observe it. In physics the principle states that on cannot assign the precise values of observable variables of a single particle even in theory. In software engineering a Heisenbug might be introduced by some force applied when debugging an application. Some Heisenbugs appear in the code, for instance within an if statement relying on System.Diagnostics.Debugger.IsAttached. With such a bug, the debugger will step into the infected code and you’re likely to spot the problem straight away. However, debuggers have more esoteric ways of introducing Heisenbugs that aren’t easily spotted. One particularly nasty Heisenbug I’ve seen a couple of times is introduced by conditional breakpoints. If you’re a C# developer and you forget that the equality operator in C# is “==” and not “=” you’re prone to Heisenbugs. Consider the following snippet:

 31 IContext context=new Context();
 32 context.Request request = new Request();
 33 context.Request.Payload = ExtractMessageBody(soapServerMessage);
 34 Uri actionUri = new Uri(soapServerMessage.Action);
 35 string serviceName = actionUri.Segments[actionUri.Segments.Length - 1];
 36 request.ServiceName = serviceName;
 37 PipelineController.Execute(context);

Let’s imagine that the implementation of the PipelineController.Execute method is complex and uses a myriad of other classes to perform the desired operation. During testing you discover that when a certain service is requested the class does not behave as expected. To save yourself from endless F11 tapping, you set a conditional breakpoint at line 35 with the condition: serviceName=”BillingService”
When you try to figure out what is going on, all sorts of weird things start to happen. Requests for the “BillingService” receive messages used with the “OrderService” and the application seems to be horribly broken.
Unexplainable behavior like this is often an Heisenbug. In the scenario described above the conditional breakpoint assigns the value “BillingService” to then serviceName variable whenever the execution pointer passes, hence the value of request.ServiceName will always be “BillingService”.  Since they’re not apparent in code, Heisenbugs like this are devious and though to spot, so be sure to pay as much attention to your break conditions as your “real” code, even during the most intense debugging sessions or else conditional breakpoints soon become a timewaster rather than a timesaver.