60

String interpolation in C#6 lets me write:

decimal m = 42.0m;
string x = $"The value is {m}";

However, a very common use case for string formatting is to specify the locale used for formatting the values. Let's say I need to use InvariantCulture for the formatting operation above, what is the syntax for that ?

This discussion suggests that I should be able to do this:

string x = INV($"The value is {m}");

Where INV is defined as

public static string INV(IFormattable formattable)
{
    return formattable.ToString(null, System.Globalization.CultureInfo.InvariantCulture);
}

However, this does not work. It compiles, but it leaves my program hanging at in cmd.exe at startup - as if klr.exe, that I assume is being invoked, hangs (Compiler bug?)

This is an ASP.NET 5 Console Project in VS15 CTP 6.

leppie
  • 115,091
  • 17
  • 196
  • 297
driis
  • 161,458
  • 45
  • 265
  • 341
  • 6
    @KeithHill The default of string interpolation is current culture not invariant. :( – Aaron Stainback Oct 18 '15 at 21:16
  • @AaronStainback Yes, thanks. I noticed that later but forgot to come back and correct my comment. – Keith Hill Oct 18 '15 at 22:46
  • @Aaron: In that case, do you have an explanation why I alwas get this error: (C# Framwork 4.6 Project in VS2015): `CA1305 (Because the behavior of 'string.Format(string, object, object)' could vary based on the current user's locale settings, replace this call in 'Function()' with a call to 'string.Format(IFormatProvider, string, params object[])'. If the result of 'string.Format(IFormatProvider, string, params object[])' will be displayed to the user, specify 'CultureInfo.CurrentCulture' as the 'IFormatProvider' parameter[...]` – eFloh Nov 10 '15 at 10:38
  • 2
    @eFloh Same reason you would get that code analysis error when using the `string.Format` overload that doesn't specify culture info. The point of this code analysis rule is to force you to explicitly specify the culture info as it's very easy for developers to overlook marking it as invariant when it needs to be (or incorrectly assume that invariant is the default culture) – Patrick M Sep 07 '16 at 02:16
  • ok, that makes sense. In that case, what we need is a cool syntax to specify the culture for interpolated strings, something like$(CultureInfo.CurrentCulture)"my {interpolated} string" or at least Current(..) as like the existing INV(...) – eFloh Sep 09 '16 at 09:14

2 Answers2

85

What you have should work. It's the correct syntax. There's also a convenient method on the "System.FormattableString" abstract class which has the same effect as the suggested "INV" helper method.

using static System.FormattableString;
...
string x = Invariant($"The value is {m}");
pharring
  • 1,991
  • 1
  • 14
  • 10
  • 2
    If this doesn't work for you, double check that you have the `using static System.FormattableString` - I somehow managed to miss it even though it's explicitly written above :) – Ohad Schneider Oct 16 '16 at 14:34
17

I finally figured this out. As it turns out, the compiler feature relies on two types, System.FormattableString, and System.Runtime.CompilerServices.FormattableStringFactory. These were not available for my project - I guess they might not yet have made it into all platforms for CTP6.

This apparently made the compiler hang as described. Once I pulled the code for those two types from the CoreCLR code and added it to my project, my code works as expected.

This was figured out through code comments for the InterpolationTests. Hooray for the source being available :-)

driis
  • 161,458
  • 45
  • 265
  • 341
  • Where do you find these assemblies? I'm using .net 4.5.2 and i'm trying to reference those but I don't see them available to reference. – Dan Csharpster Dec 04 '15 at 18:27
  • 2
    According to https://msdn.microsoft.com/en-us/library/system.formattablestring%28v=vs.110%29.aspx, it first appears in 4.6. – Arthur Ward Jan 27 '16 at 19:56