【问题标题】:Can I pass parameters to String.Format without specifying numbers?我可以在不指定数字的情况下将参数传递给 String.Format 吗?
【发布时间】:2009-02-18 13:56:48
【问题描述】:

有没有办法String.Format 一条消息而不必指定{1}, {2}, 等?是否有可能有某种形式的自动增量? (类似于普通的老printf

【问题讨论】:

  • 不使用数字的目的是什么?也许如果我们可以了解您想要避免使用它们的原因,我们会提供更有用的解决方案...
  • 我大概有20个参数,每一个都写一个数字比较麻烦。我也担心我可能会错过一个数字,或者使用一个数字两次。而且我觉得没有数字的可维护性可能更容易。
  • 我想可以理解...如果我想将尚未格式化的字符串嵌入到其他尚未格式化的字符串中...然后在过程结束时附加参数,我总是觉得很费力这也有同样的缺点。
  • 使用索引,您不受所提供参数的顺序的约束。当您想要翻译该格式字符串时,这很好。
  • 对于 C#7,答案已经过时,因为它包括 "string interpolation",就像在 Perl 中一样:$"{name} is {age} year{(age == 1 ? "" : "s")} old." --> Horace 34 岁

标签: c# .net string formatting


【解决方案1】:

您可以使用named string formatting 解决方案,它可能会解决您的问题。

【讨论】:

  • 谢谢。很高兴知道它。
【解决方案2】:

恐怕不会——它将对象放入字符串的什么位置?使用 printf,您仍然需要在某处放置说明符。

【讨论】:

  • 是的,我不介意使用说明符,但我不想对索引进行硬编码。
  • @Hosam - 这是为了在可格式化字符串中嵌入其他可格式化字符串,然后在稍后阶段添加所有参数?
  • @balabaster:不,这是对String.Format 的一次调用以插入一些变量。
【解决方案3】:

我认为最好的方法是传递属性名称而不是数字。 使用这个方法:

using System.Text.RegularExpressions;
using System.ComponentModel;

public static string StringWithParameter(string format, object args)
    {
        Regex r = new Regex(@"\{([A-Za-z0-9_]+)\}");

        MatchCollection m = r.Matches(format);

        var properties = TypeDescriptor.GetProperties(args);

        foreach (Match item in m)
        {
            try
            {
                string propertyName = item.Groups[1].Value;
                format = format.Replace(item.Value, properties[propertyName].GetValue(args).ToString());
            }
            catch
            {
                throw new FormatException("The string format is not valid");
            }
        }

        return format;
    }

假设您有一个 Student 类,其属性如下:Name、LastName、BirthDateYear 并像这样使用它:

 Student S = new Student("Peter", "Griffin", 1960);
 string str =  StringWithParameter("{Name} {LastName} Born in {BithDate} Passed 4th grade", S);

你会得到:1960 年出生的彼得格里芬通过了四年级。

【讨论】:

    【解决方案4】:

    有一个 C# 实现 printf available here

    【讨论】:

      【解决方案5】:

      人们总是可以使用这种(未经测试的)方法,但我觉得它过于复杂:

      public static string Format(char splitChar, string format,
                                  params object[] args)
      {
          string splitStr = splitChar.ToString();
          StringBuilder str = new StringBuilder(format + args.Length * 2);
          for (int i = 0; i < str.Length; ++i)
          {
              if (str[i] == splitChar)
              {
                  string index = "{" + i + "}";
                  str.Replace(splitStr, index, i, 1);
                  i += index.Length - 1;
              }
          }
      
          return String.Format(str.ToString(), args);
      }
      

      【讨论】:

        【解决方案6】:

        我想出了这个,虽然有点麻烦,但它适用于我需要做的事情,即以与使用 WriteLine 相同的方式将变量数或参数传递给我自己的函数。我希望它可以帮助某人

        protected void execute(String sql, params object[] args)
        {
            for (int i = 0; i < args.Count(); i++ )
            {
                sql = sql.Replace(String.Format("{{{0}}}", i), args[i].ToString());
            }
            //...
        }
        

        【讨论】:

        • 你能告诉我你是在哪个程序中实现的吗?我想做一些 SQL 注入。所以说实话,你真的应该考虑在SqlCommand 中使用SqlParameter 来替换它
        【解决方案7】:

        如果有人感兴趣,我已经修改了 Ashkan 的解决方案,使其能够在 WinRT 下运行:

        /// <summary>
        /// Formats the log entry.
        /// /// Taken from:
        /// http://stackoverflow.com/questions/561125/can-i-pass-parameters-to-string-format-without-specifying-numbers
        /// and adapted to WINRT
        /// </summary>
        /// <param name="format">The format.</param>
        /// <param name="args">The arguments.</param>
        /// <returns></returns>
        /// <exception cref="System.FormatException">The string format is not valid</exception>
        public static string FormatLogEntry(string format, object args)
        {
            Regex r = new Regex(@"\{([A-Za-z0-9_]+)\}");
        
            MatchCollection m = r.Matches(format);
        
            var properties = args.GetType().GetTypeInfo().DeclaredProperties;
        
            foreach (Match item in m)
            {
                try
                {
                    string propertyName = item.Groups[1].Value;
                    format = format.Replace(item.Value, properties.Where(p=>p.Name.Equals(propertyName))
                        .FirstOrDefault().GetValue(args).ToString());
                }
                catch
                {
                    throw new FormatException("The string format is not valid");
                }
            }
        
            return format;
        }
        

        【讨论】:

          猜你喜欢
          • 2020-12-12
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-11-06
          • 2018-07-10
          • 1970-01-01
          • 2013-01-05
          • 1970-01-01
          相关资源
          最近更新 更多