[.NET Gotcha] SettingsPropertyValue typed as a string will never be null
I like to use chained null coalesce operators (??) to handle default console application parameters. The idea is that I provide a default value, override it via application settings (app.config and user.config), and then overridede it with command-line arguments. I think it provides for a nice user experience - if you're always going to to run the application with the same settings, you can set them in the config; if you need to script it you can control everything from the command-line.
Unfortunately, this doesn't appear to work for string valued settings, since they will always return at least string.Empty. Here's the example code:
string logFilename = arguments["logFile"] ?? Settings.Default.logFile ?? "application.log";
The intent is to check for command-line arguments, then application settings, and if both are missing to use the default value. However, Settings.Default.logFile (a System.Configuration.SettingsPropertyValue) will never be null and thus the null coalesce operator (??) is worthless in this case:
If there is no serialized value to deserialize when the deserialization is attempted, then SettingsPropertyValue object will instead attempt to return a default value if one was configured as defined on the associated SettingsProperty instance. In this case, if the DefaultValue property was set to either a null reference (Nothing in Visual Basic), or to the string "[null]", then the SettingsPropertyValue object will initialize the PropertyValue property to either a null reference (Nothing in Visual Basic) for reference types, or to the default value for the associated value type. On the other hand, if DefaultValue property holds a valid object reference or string value (other than "[null]"), then the DefaultValue property is returned instead. If there is no serialized value to deserialize when the deserialization is attempted, and no default value was specified, then an empty string will be returned for string types.
A better pattern would be a function which takes the key ("logFile") and uses string.IsNullOrEmpty() to determine if it should move on to the next setting source. If it was vital that a setting be nullable, it would be possible to use a StringCollection, but that still wouldn't support simple ?? chaining.