I haven't posted an entry here in a while as I have a lot on my plate! I started a new job and am truly enjoying it. I work with a lot of very intelligent people, and am learning each and every day at a level that I haven't seen since I first started programming. This new job, however, comes with a code base that isn't always spectacular. This isn't unlike most positions you would find as a Software Engineer, but today a naming decision came to bite us in the butt, and nobody saw it coming.
.Net Version 4.6 added the System.AppContext class. If your .NET project is targeting 4.5 or lower and has its own class named AppContext with the namespace imported in a using directive, your project will build but will fail at run time on any machine with .NET 4.6 or later installed due to an ambiguous reference.
I decided to assist a couple other developers who are planning for the long-awaited upgrade to Visual Studio 2015, as we're all currently on 2012. Waiting for it to install, I chunked away at some overdue documentation until it was done. Everything went smoothly, I had the latest and greatest! Yay! Time to code:
The project is targeting .NET 4.5, and was building without errors. When I ran the project, I started getting a strange runtime error that I had never seen with this project... It was telling me that a reference was ambiguous. "How can I have an ambiguous reference that the compiler didn't catch for me, and why did this just show up without me changing any of the related code? The code was working in our QA environment... It must have been something that changed when I installed VS 2015." Well, I was correct.
.NET 4.6 contains a new class in the System namespace called AppContext.
A long, long, long time ago in a software company far, far, far away... someone created a class in our project that they named "AppContext." Most of our files reference the System namespace. Now we're left with a few questions:
- Why did it build successfully?
- Why is it a runtime error?
- Where do I point the finger, my company or Microsoft?
After losing what little hair I have left, I found the following (with help from some coworkers, of course!)
Why did it build successfully?
We were targeting the .NET 4.5 framework, which did not contain the System.AppContext class. When it compiled, it found no ambiguous references since it was compiling against 4.5.
Why is it a runtime error?
Just as Semantic Versioning instructs us, we should never release a minor if there are breaking changes. As far as the .NET framework goes, there were no breaking changes! It just happened to conflict with our existing code. Another caveat that we found is that when .NET does an update for a minor version, it does an In-Place Upgrade, which basically means it overwrites the previous version. This is typically fine since .NET is backwards compatible, but in this case it meant that this System.AppContext class was available in the GAC. Even though we were targeting .NET 4.5, it was using .NET 4.6 to run the code in all of its backwards compatible glory!
Where do I point the finger, my company or Microsoft?
If I had to choose where to point the finger, it'd be a bit of a split decision, which may take some explaining, as most of you reading this have already made up your mind that we probably shouldn't have used the name AppContext for a class in our production application.
The reason I assign some blame to Microsoft is that AppContext is a widely used class, and by adding it to the System namespace directly, rather than a more specific namespace that's less likely to conflict with other code, they have introduced a regression in a lot of software, some of which is legacy code, others aren't even aware of, or some that are now instructing customers not to upgrade to the newest version of .NET.
Naming is more important than simply making code readable and easy to understand; if you use reserved words, or words that are commonly used elsewhere, you are asking for trouble, and it will come back to bite you in the ass one day in the future, even if it's 10 years from now.