【问题标题】:String Interpolation in Visual Studio 2015 and IFormatProvider (CA1305)Visual Studio 2015 和 IFormatProvider 中的字符串插值 (CA1305)
【发布时间】:2015-08-18 15:39:15
【问题描述】:

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

Dim s = $"Hello {name}"

但是如果我使用它,代码分析会告诉我我破坏了CA1305: Specify IFormatProvider

过去我是这样做的:

Dim s = String.Format(Globalization.CultureInfo.InvariantCulture, "Hello {0}", name)

但是新样式怎么办呢?

不得不提的是,我正在寻找 .Net 4.5.2 的解决方案(适用于 .Net 4.6 dcastro has the answer)

【问题讨论】:

标签: c# .net vb.net visual-studio-2015 string.format


【解决方案1】:

您将使用 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);

您需要针对 Framework 4.6 进行编译,因为 IFormattable 和 FormattableString 是旧版本中不存在的类。所以如果你的目标是旧版本的 .NET 框架,你不能在不触发错误的情况下使用插值语法。

除非您应用一点技巧(adapted to compile against 4.6 RTM from Jon Skeet's gist 和 forked to my own account.)。只需将一个类文件添加到您的项目中,其中包含:

更新

现在还有一个Nuget package available that will provide the same functionality to your project(感谢@habakuk 引起我的注意)。

install-package StringInterpolationBridge

或者,如果您想在不向产品添加额外程序集的情况下实现相同的目标,请将以下代码添加到您的项目中:

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);
        }
    }
}

见:

【讨论】:

【解决方案2】:

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

来自Customizing string interpolation in C# 6,作者:Thomas Levesque

此功能的一个鲜为人知的方面是内插字符串可以被视为String 或IFormattable,具体取决于上下文。

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

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

【讨论】:

  • 谢谢,但我仍在使用 4.5.2(因为 blogs.msdn.com/b/dotnet/archive/2015/07/28/… - 但现在可能已修复)。 4.5还有解决方案吗?
  • @habakuk 不,我不这么认为。
  • 请注意,您仍在使用 4.5.2 的错误已得到修复。运行 Windows 更新来解决问题。
  • @habakuk 如果您阅读了链接的 Levesque 文章,似乎有!查看Jon Skeet's method
  • @default.kramer 不幸的是,该要点不再有效,但修复它并不难。看我的回答。
【解决方案3】:

Microsoft 使string interpolation 的使用和遵守CA1305: Specify 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}");

但是,如果您的目标是通过当前文化完成插值,那么在 .NET Core 3.0 中提出了一个伴随的静态方法 FormattableString.CurrentCulture(目前为预览版 5):

using static System.FormattableString;

string name = CurrentCulture($"Hello {name}");

【讨论】:

    【解决方案4】:

    我找到了一个 Nuget 包,其中包含 jessehouwing presented in his answer 的代码。

    Nuget 包 'StringInterpolationBridge' (source) 将此代码添加到每个项目中。

    【讨论】:

    • 我希望您不介意我将这个宝石添加到已经接受的完整答案中。感谢您引起我的注意!
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-29
    相关资源
    最近更新 更多