我将如何编写 String.Format 扩展方法?

Posted

技术标签:

【中文标题】我将如何编写 String.Format 扩展方法?【英文标题】:How Would I write a String.Format Extension Method? 【发布时间】:2013-05-17 14:55:04 【问题描述】:

我在 C# 代码中使用String.Format 可能比if 语句之外的任何东西都多。

string ask = String.Format("Continue using [0]?", value);

我刚刚开始考虑我使用它的频率。

接下来,我开始思考为它创建一个Extension Method 会有多棒。

ask.Format("Continue using [0]?", value);

所以,我查看了String.Format,它有很多重载,因为有很多方法可以调用它。

Format(String, Object) Format(String, Object[]) Format(IFormatProvider, String, Object[]) Format(String, Object, Object) Format(String, Object, Object, Object)

嗯……这让事情变得复杂了。

是否有一种简单的方法来编写 Extension Method 以简单地构建在 System.String 命名空间中已经存在的重载之上?

这是我想看到的:

public static class Extensions

  public static String Format(this String str, String formatText, /* What goes here? */)
  
    return str.Format(formatText, /* Magic */);
  

我想我可以编写一个重载来匹配每个 String.Format 重载,但这可能不是必需的。

【问题讨论】:

【参考方案1】:
ask.Format("Continue using [0]?", value);

不是我会使用它的方式。这就是我要做的:

var ask = "Continue using [0]?".FormatWith(value);

这是我的扩展方法:

public static string FormatWith(this string value, params object[] args)

    return String.Format(value, args);

【讨论】:

迈克,我稍微编辑了你的代码以包含formatText 字符串。否则,这就像我想要的那样工作。 我应该把那个方法放在哪里 在您的项目/解决方案中任何位置的静态类中:msdn.microsoft.com/en-us/library/bb383977.aspx【参考方案2】:

您想修改调用字符串。你不能那样做。 .Net 中的字符串不会改变(它们是不可变的),因此您仍然必须返回一个新字符串。您可以从 C# 获得的最接近的代码是这样的:

string ask = $"Continue using [value]?";

如果您可以通过引用传递扩展对象,则可以修改您的原始字符串。不幸的是,C# 不支持这一点。

有趣的是IL确实支持它,你可以使用VB.Net编写你想要的方法:

<Extension()> _
Public Shared Sub Format(ByRef str As String, ByVal formatText As String, ByVal ParamArray args As Object())
    str = String.Format(formatText, args);
End Sub

不幸的是,即使您将其填充到 VB.Net 类库项目中,您也无法从 C# 调用它,因为 C# 要求您在调用函数时在调用站点使用 ref 关键字参数通过引用,并且没有用于扩展方法的语法。

有关与您所需语法不完全匹配但仍会为您提供相当不错的解决方法,请参阅Mike Cole's answer。

【讨论】:

【参考方案3】:

您很接近,只缺少params object[] args 参数:

public static class Extensions

  public static String Format(this String str, 
                              String formatText, 
                              params object[] args)
  
    return str.Format(formatText, args);
  

【讨论】:

这不是无限递归吗? 是的,但我很快就明白了他的意思。他可能只是使用了我未经测试的示例代码,这已经是无限递归的。【参考方案4】:

使用字符串插值(在 C# 6.0 和 VS 2015+ 中)。您的代码如下所示:

var ask = $"Continue using [value]?";

在我发现字符串插值之前,我一直在使用 String.Format 或字符串连接,现在我被迷住了。

这样做的一个潜在缺点是您无法将格式字符串分解为常量或资源。在这里查看更多详细信息:

https://msdn.microsoft.com/en-us/library/dn961160.aspx

本文介绍了更多详细信息,并包含了其他一些不错的宝石。 Definitley 值得一读:

https://msdn.microsoft.com/en-us/magazine/dn879355.aspx

【讨论】:

公平地说,自 VS 2015 以来,我们只能在 C# 中执行此操作,因此有 很多 旧代码没有使用它. @IanMcLaird 好点。这对于支持/重构旧代码库可能不会那么有用。但它非常适合新项目。

以上是关于我将如何编写 String.Format 扩展方法?的主要内容,如果未能解决你的问题,请参考以下文章

从一个方法返回两个变量

如何解决 Lua 中 string.format 参数不正确抛出异常问题

string.format(format,doubleValue) ,精度丢失

如何在 Scala 中使用 java.String.format?

如何使用 String.Format 将布尔类型转换为“ON”“OFF”

String.format()方法求教~