This page briefly describes some weird issues you may encounter in the .NET Framework, with links to more detailed discussions. My criterion for selecting these issues was my bafflement when I encountered them.
Additionally, there are some weird .NET performance issues that I discuss elsewhere. User-defined value types can be surprisingly slow due to inadequate CLR JIT optimizers; and WPF drawing performance can be improved by disabling anti-aliasing and freezing all eligible objects.
If you look at a Visual Studio solution file, you’ll find that the .NET platform identifier for “pick x86 or x64 at runtime” is spelled
Any CPU – note the space! But if you look at a Visual Studio project file, the equivalent platform identifier is spelled
AnyCPU – without a space.
This is not because MSBuild ignores embedded spaces, as you will discover when you try to target
AnyCPU on a solution file or
Any CPU on a project file. Rather, it’s a silly legacy issue that MSBuild silently works around by substituting one spelling for the other when propagating solution settings to projects.
A Microsoft Connect item has been opened for this issue – and closed as “Won’t Fix” in late 2009. Guess we’ll never see a fix for that one, so you simply have to be aware that projects require a different platform identifier than solutions.
System.Configuration namespace provides a convenient mechanism called Application Settings to semi-automatically manage and upgrade your application’s user settings. The MSDN Library page Application Settings Architecture gives an overview of this mechanism.
Unfortunately, it also contains an error. Section “Settings File Location” claims that the configuration file for the current user is stored in the folder
Application.LocalUserAppDataPath, just as you’d intuitively expect. But if you look there, you’ll find one or more folders with very strange names instead.
As it turns out, Application Settings creates a new folder for every new version of your application, and the folder name encodes the current version. The marked reply in this MSDN Forum thread explains the exact composition of the folder name.
If you wish your next application version to continue using the previous version’s settings, you must explicitly call an
Update method to retrieve the settings from the older version’s folder, as described in this Stack Overflow thread.
On the other hand, if you wish Application Settings wouldn’t litter your file system with a hundred strangely named folders in the first place, you’re out of luck. The default
LocalFileSettingsProvider that defines these folder names does not expose any way to change them. You would have to implement an entire new custom settings provider, as explained in the Application Settings Architecture article, but for my part I’d rather use
XDocument to manage my settings manually.
Platform targeting in .NET applications employs a confusing jumble of project and solution settings that look identical but are actually independent. The AnyCPU Versus Any CPU spelling hack is a relatively harmless example. Much more serious is the possibility of mismatched explicit target platforms after repeated editing of project and solution settings.
Galaktor’s thorough article Targeting Platforms in Visual Studio explains how target platforms are specified in solution and project files, how those settings can go out of sync, and how to avoid that. I prefer to clean up my solution and project files by hand rather than through the laborious Visual Studio UI, but I definitely agree with his recommendation to keep them in source code control so you notice immediately when some setting has changed that shouldn’t have.
When an exception occurs in the constructor of a WPF code-behind class, the Visual Studio 2008/2010 debugger confusingly reports a
XamlParseException with no indication of the faulty source code line. When running outside the debugger, the Windows 7 application failure dialog likewise reports a XAML exception. But there is in fact nothing wrong with either your XAML code or the parsing thereof. To find the actual exception, you need to drill down through two levels of
This section covers two issues, both stemming from the bizarre way WPF handles input focus. The matter is discussed at length in the aptly titled MSDN Forums thread A FocusScope Nightmare.
WPF windows distinguish multiple “focus scopes” which are predefined for menus and toolbars, and can be defined for any control via FocusManager.IsFocusScope. What the MSDN Library leads you to believe is that focus scopes can be created at will, to remember each focused element in various subsections of a window.
But in reality, it’s a very limited hack that’s just about good enough to make menus and toolbars work – while accidentally breaking routed commands. First, setting
IsFocusScope on your own controls will result in very strange behavior. See Daniel Grunwald’s Code Project article on what can happen, and how to create your own focus scope mechanism that works properly.
Accidentally disabled commands are the other casualty of this design. Since the goal was to dispatch menu and toolbar commands to input controls in the main window, i.e. the parent focus scope, WPF simply disables any routed commands for menu and toolbar items whose targets cannot receive keyboard input – without even evaluating their
CanExecute handlers! If an item’s
CommandTarget is a null reference (the default), WPF substitutes the currently focused element in the parent scope for this target check. This means that WPF will merrily disable your entire main menu if a non-interactive image is focused…
Fortunately, the workaround is just a few lines of code. During creation of your main window, loop through all menu and toolbar items and set their
CommandTarget to the main window itself. A window can always receive keyboard input, and a valid
CommandTarget prevents WPF from checking the focused element in the parent scope. Your routed commands will now properly evaluate their
CanExecute handlers to decide if they should be enabled, regardless of whether some focused element can receive input.
WPF provides a convenient Path Markup Syntax to define geometric figures in compact text strings of one-letter commands and drawing coordinates. The static method
Geometry.Parse translates such strings into frozen
First, you should be aware of some undocumented behavior. Path markup syntax offers no way to specify whether a given figure should be filled or not. Therefore,
Geometry.Parse simply sets the
isFilled parameter to
There is another confusing consequence due to a strange bug in WPF 4. As you can see in this Stack Overflow question, certain figures drawn with dashed lines won’t render correctly unless