Visual Studio 2015和IFormatProvider中的字符串插值(CA1305)

hab*_*kuk 29 .net c# vb.net string.format visual-studio-2015

Visual Studio 2015中的新字符串插值样式是这样的:

Dim s = $"Hello {name}"
Run Code Online (Sandbox Code Playgroud)

但是,如果我使用它,代码分析告诉我,我打破CA1305:指定IFormatProvider

在过去,我这样做:

Dim s = String.Format(Globalization.CultureInfo.InvariantCulture, "Hello {0}", name)
Run Code Online (Sandbox Code Playgroud)

但是如何用新风格来完成呢?

我必须提一下,我正在寻找.Net 4.5.2的解决方案(.Net 4.6 dcastro有答案)

jes*_*ing 21

你要使用System.FormattableString或者System.IFormattable类:

IFormattable ifs = (IFormattable)$"Hello, {name}";
System.FormattableString fss = $"Hello, {name}";

// pass null to use the format as it was used upon initialization above.
string ifresult = ifs.ToString(null, CultureInfo.InvariantCulture);
string fsresult = fss.ToString(CultureInfo.InvariantCulture);
Run Code Online (Sandbox Code Playgroud)

你必须对编译框架4.6,因为IFormattableFormattableString是不旧版本中存在的类.因此,如果您的目标是旧版本的.NET框架,则无法在不触发错误的情况下使用插值语法.

除非你应用一点hack(适合从Jon Skeet的要点编译4.6 RTM分叉到我自己的帐户.).只需在项目中添加一个类文件,其中包含:

更新

现在还有一个Nuget软件包可以为您的项目提供相同的功能(感谢您将此注意到@habakuk).

install-package StringInterpolationBridge
Run Code Online (Sandbox Code Playgroud)

或者,如果要在不向产品添加其他程序集的情况下实现相同的功能,请将以下代码添加到项目中:

namespace System.Runtime.CompilerServices
{
    internal class FormattableStringFactory
    {
        public static FormattableString Create(string messageFormat, params object[] args)
        {
            return new FormattableString(messageFormat, args);
        }
    }
}

namespace System
{
    internal class FormattableString : IFormattable
    {
        private readonly string messageFormat;
        private readonly object[] args;

        public FormattableString(string messageFormat, object[] args)
        {
            this.messageFormat = messageFormat;
            this.args = args;
        }

        public override string ToString()
        {
            return string.Format(messageFormat, args);
        }

        public string ToString(string format, IFormatProvider formatProvider)
        {
            return string.Format(formatProvider, format ?? messageFormat, args);
        }

        public string ToString(IFormatProvider formatProvider)
        {
            return string.Format(formatProvider, messageFormat, args);
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

看到:

  • 此外,如果您使用的是.NET 4.6或StringInterpolationBridge,则可以使用辅助方法来创建文化字符串:FormattableString.Invariant:https://msdn.microsoft.com/en-us/library/system.formattablestring.invariant (3认同)

dca*_*tro 12

如果您的目标是.NET Framework 4.6,则可以利用字符串插值可隐式转换为FormattableString以下事实:

来自Thomas Levesque 在C#6中自定义字符串插值

该特征的一个鲜为人知的方面是内插字符串可以被视为a String或者视为IFormattable上下文.

static string Invariant(FormattableString formattable)
{
    return formattable.ToString(CultureInfo.InvariantCulture);
}

string text = Invariant($"{p.Name} was born on {p.DateOfBirth:D}");
Run Code Online (Sandbox Code Playgroud)


Dav*_*dRR 6

Microsoft 使使用字符串插值变得更容易并符合CA1305:指定 IFormatProvider

如果您使用的是 C# 6 或更高版本,则可以访问该using static指令。

此外,静态方法FormattableString.Invariant可用于.NET Standard 1.3.NET Core 1.0.NET Framework 4.6及更高版本。将两者放在一起可以让你做到这一点:

using static System.FormattableString;

string name = Invariant($"Hello {name}");
Run Code Online (Sandbox Code Playgroud)

但是,如果您的目标是通过当前区域性完成插值,则.NET Core 3.0(当前为预览版 5)中FormattableString.CurrentCulture提出了一个配套的静态方法:

using static System.FormattableString;

string name = CurrentCulture($"Hello {name}");
Run Code Online (Sandbox Code Playgroud)