C# 6 Interpolated Strings and Code Analysis (CA1305)

2015-09-09

C# 6 introduces a new concept, Interpolated Strings, sort of the compiler version of String.Format. It's a great way to ensure that the compiler checks that your variables actually exist and that you're passing the right number of 'm.

And as with String.Format it's important to pass the correct CultureInfo to it to ensure that you're showing the right date formats, "." or "," as decimal separator etc.

By default it will use the CurrentCulture, which makes sense when formatting data to display them in the User Interface. In many other cases, however, you'd want to format your data in Invariant form, when writing to a file, calling an external service or storing data in a database.

To ensure that you, as a developer have thought about this, there is a Static Code Analysis rule that ships with Visual Studio, CA1305: Specify IFormatProvider. Unfortunately the documentation of this rule has not been updated to show how to supply the IFormatProvider or CultureInfo to an Interpolated String.

There are multiple ways to handle this, but all involve casting the Interpolated String to a FormattableString or a IFormattable. The way that's the most straightforward is to cast the formattable string and then call .Tostring on it:

FormattableString fss = $"Hello, {name}";
fss.ToString(CultureInfo.InvariantCulture);

While this works, it'll probably drive every developer crazy, having to create a variable or being creative with casting:

((FormattableString) $"Hello, {name}").ToString(CultureInfo.InvariantCulture);

which won't make your code easier to read one bit, I'd almost stick to String.Format ;).

There is a very interesting trick which combines another C#6 feature, static imports and the calling the Invariant method:

using static System.FormattableString;
...
string x = Invariant($"The value is {m}");

Unfortunately, Microsoft decided to not create a static CurrentUI nor the static Current variant, which I feel is a shame. Or course it would not take much to create your own versions of these static methods:

public static string Current(FormattableString formattable)
{
    if (formattable == null)
    {
        throw new ArgumentNullException("formattable");
    }
    return formattable.ToString(Globalization.CultureInfo.CurrentCulture);
}

public static string CurrentUI(FormattableString formattable)
{
    if (formattable == null)
    {
        throw new ArgumentNullException("formattable");
    }
    return formattable.ToString(Globalization.CultureInfo.CurrentUICulture);
}

See also:

 

Most Reading