C# Interpolated Strings in older .NET frameworks

2015-09-09

When targeting a .NET 4.0 or 4.5 project it's not possible by default to use the Interpolated Strings and their FormattableString and IFormattable counterparts. By default

But, this is only because these two types didn't ship with the older version of the .NET Framework. If you make sure these classes are available to the C#6 compiler, it will happily produce an assembly which is compatible with the older versions of the .NET framework, since these interpolated strings are a language feature and not dependent on the Common Language Runtime.

You'll need these classes to pass a CultureInfo in order to satisfy Code Analysis 1305.

Someone beat me to creating a NuGet Package of the classes required, which makes this as simple as running:

install-package StringInterpolationBridge

C# 6 Interpolated Strings and Code Analysis (CA1305)

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:

 

Search This Blog

Loading...

Most Reading