Weird .NET Issues

This page describes some weird issues you may encounter in the .NET Framework. 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.

AnyCPU Versus Any CPU

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.

Application Settings Folders

The 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. Subsection “Settings File Location” (under “Settings Persistence”) 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

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.

Raphael Estrada’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.

WPF Constructor Exceptions

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 InnerException properties.

WPF Focus Disables Commands

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 Path Markup Syntax

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 StreamGeometry objects.

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 true for all implicitly generated BeginFigure calls. That means you cannot use path markup syntax if you specifically wish to create unfilled figures.

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 isFilled is true! So if you get strangely different output for the same figure, depending on whether you use path markup syntax or method calls, you should try setting isFilled to true on your BeginFigure calls.