Notes from West London

Wednesday, February 15, 2006

Oddness in .NET

I've been making C# examples to show how a typecast is governed by both classes and assemblies. This reflects that a type in .NET is defined as an assembly+class pair. My examples are somewhat edge cases, and only apply to the CLR (not Mono), but they do imitate the programming used in plug-in frameworks, where assemblies loading is explicitly controlled.

Ordinarily, source code doesn't need to worry about which assembly defines a class. For example, if class A { ... } is deployed in assembly Animal, and class D : A {... } is in assembly Dog, then as long as client code has references to Animal and Dog assemblies, it can cast D objects to A (or System.Object) and back down to D with impunity.

The complexity comes when you have the Animal assembly loaded automatically by the system, and the Dog assembly loaded by the programmer. By itself, that scenario is OK. But I found that, on loading the Dog assembly, the system would under certain circumstances load the Animal assembly again. Then, you get a "clash" between the two loaded Animal assemblies, because while their contents are identical, their locations on disk are different. And on-disk location matters.

The fact that Animal being loaded twice causes problems is not news. What's news are the circumstances when it happens. Essentially, it happens when I wouldn't expect it to happen, and it doesn't happen when I would expect it to. I thought I understand all the in's and out's of assembly loading in the CLR, including (but not limited to :-) loading contexts, order-dependence, bytecode verification, and auto-extension of probing paths. But I can't reason about why the behaviour of the system is the opposite of what I expected. We will see if Microsoft can comment on the scenarios I sent.

0 Comments:

Post a Comment

<< Home