【问题标题】:Format placeholder in string.format to pick substring of an argument格式化 string.format 中的占位符以选择参数的子字符串
【发布时间】:2019-08-29 14:56:48
【问题描述】:

C#string.Format 方法是否有一个格式字符串,可以从相应的参数中选择一个子字符串?像这样:

var lang1 = "EN";
var lang2 = "FR";

var shortFormat = "Foo-{0:0-0}.pdf";
var longFormat = "Foo-{0:0-1}.pdf";

string.Format(shortFormat, lang1) // Foo-E.pdf
string.Format(shortFormat, lang2) // Foo-F.pdf
string.Format(longFormat, lang1) // Foo-EN.pdf
string.Format(longFormat, lang2) // Foo-FR.pdf

预测几个 cmets:是的,我知道 Substring 方法。我也读过 string.Format 比简单的 Substring 慢。上面的例子被大大简化了。假设 string.Format 语句位于一个位置,而 lang1/lang2 参数是来自另一个位置的输入,而 shortFormat/longFormat 是在 resx 文件中定义的。

也就是说,在要定义格式的地方,我们对被格式化的值(示例中的 lang1/lang2)一无所知,也没有任何方法可以执行 C# 代码。因此我们不能在值上调用任何方法,例如Substring。在格式化代码运行的地方,反过来,我们将格式作为参数,所以我们不能简单地对值执行Substring,因为我们不知道格式是否需要它(除非如果我们检查格式)。

【问题讨论】:

    标签: c# string-formatting


    【解决方案1】:

    不,string.Format 没有这个功能,这里有更好的解释:Can maximum number of characters be defined in C# format strings like in C printf?

    如果您不想使用 Substring,我将为 string 创建一个扩展类,如下所示:http://msdn.microsoft.com/en-us/library/bb311042.aspx

    namespace CustomExtensions
    {
        public static class StringExtension
        {
            public static string ShortFormat(this string str)
            {
                // manipulate and return str here
            }
            public static string LongFormat(this string str)
            {
                // manipulate and return str here
            }
        }
    }
    

    【讨论】:

    • 感谢您的回答。我以前很怕那个。至于扩展方法的建议 - 我认为这仍然不能解决我的问题,正如我在“预期”部分中提到的那样:在定义格式的地方(例如在 resx 文件中),值未知.这就是为什么Substring 或它上面的任何扩展方法都无法访问它的原因。
    • 哦,好的。然后相当困难=/
    【解决方案2】:

    XSLT formatting 可以是一个选项:用户可以在配置文件中提供几乎所有内容,如果需要,甚至可以在您的域中执行自定义 c# 代码。

    还请注意,格式的更改可能仅限于相对少量的操作:裁剪、填充或在某些位置插入一两个东西。每个都可以设置为单独的功能,并提供自己的参数。

    【讨论】:

      【解决方案3】:

      有两种方法可以提供自定义格式。您可以在自定义类型上实现 IFormattable 以控制该类型始终格式化的方式,或实现 IFormatProvider 以覆盖其他类型在特定情况下的格式化方式。

      在您的情况下,我建议创建一个新类型来封装您的软件如何处理语言代码;

      public struct LanguageCode : IFormattable {
         public readonly string Code;
         public LanguageCode(string code) {
            Code = code;
         }
      
         public override string ToString()
            => this.ToString("L", CultureInfo.CurrentCulture);
         public string ToString(string format)
            => this.ToString(format, CultureInfo.CurrentCulture);
      
         public string ToString(string format, IFormatProvider provider){
            if (String.IsNullOrEmpty(format))
               format = "L";
            if (provider == null)
               provider = CultureInfo.CurrentCulture;
            switch (format.ToUpperInvariant()){
               case "L": // Long
                  return Code.ToString(provider);
               case "S": // Short
                  return Code.SubString(0,1).ToString(provider);
               default:
                  throw new FormatException($"The {format} format string is not supported.");
            }
         }
      
         public static implicit operator LanguageCode(string code)
            => new LanguageCode(code);
         public static implicit operator string(LanguageCode language)
            => language.Code;
      }
      

      然后从你的例子;

         var lang1 = (LanguageCode)"EN";
         LanguageCode lang2 = "FR";
      
         var shortFormat = "Foo-{0:S}.pdf";
         var longFormat = "Foo-{0:L}.pdf";
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-06-16
        • 1970-01-01
        • 2013-08-13
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多