Hideous C# Versioning Bug

Thanks to Jason Whittington and Peter Drayton for helping me figure this out.

UPDATE! This appears to be a C# compiler bug, as peverify.exe pukes on client.exe. So the ultra good news is that this code won't run in an environment where it's not granted SkipVerification. Still, don't let this happen to you.

I was playing around with versioning in the CLR today, and I started to wonder what would happen under the following scenario:

Someone writes a component - call it Foo - and deploys another component - say A - that uses it. They also have a client that uses A. Later, they version Foo to v2, and build component B against it. Then they add code to the client to work with B. Both A and B have methods that accept a Foo as a parameter, but A has been compiled against Foo v1, and B has been compiled against Foo v2. The client has been updated to work with the latest Foo v2.

Here's the picture that shows what everyone is built against

Now, the terrible part comes when the client creates a Foo and passes it to A. A thinks it's getting a Foo v1, but it's really getting a Foo v2. And the truly awful bit is, it acts as if it were a Foo v1, right down to going after the wrong bits of memory and calling the wrong methods.

Click here to download some code that demonstrates this. Simply extract the files into some directory, run nmake to build everything, and then run client. Observe the output, and tell me if you think that's what you'd expect based on looking at client.cs.

Here's another variation that actually crashes the process. That's usually (incorrectly) thought to be impossible without writing unsafe or unmanaged code.