【问题标题】:String.Format() - Repassing params but adding more parametersString.Format() - 重新传递参数但添加更多参数
【发布时间】:2012-05-08 17:41:14
【问题描述】:

我想做这样的事情:

public string GetMessage(params object otherValues[]) {
    return String.Format(this.Message, this.FirstValue, otherValues);
}

所以,我想将参数数组重新传递给String.Format(),但要添加一个新参数。

最好的方法是什么,知道我们可以“重建”一个新的对象数组,但这似乎不太好。

【问题讨论】:

    标签: c# .net string-formatting params-keyword


    【解决方案1】:
    public string GetMessage(params object[] otherValues)
    {
        return String.Format(this.Message, new[] { this.FirstValue }.Concat(otherValues).ToArray<object>());
    }
    

    【讨论】:

    • 不幸的是,ToArray() 构建了一个新结构。
    【解决方案2】:

    您可以使用ConcatToArray 扩展方法:

    public string GetMessage(params object[] otherValues) 
    {
        var values = new[] { this.FirstName }.Concat(otherValues).ToArray();
        return String.Format(this.Message, values);
    }
    

    【讨论】:

    • 这正是我所看到的 :-) 它不会。添加它。谢谢。
    • this.FirstName 放在otherValues 的第一个元素之前,就像OP 在他们的问题中所说的那样吗?
    【解决方案3】:

    如果other 参数经常很少,我会使用现有的重载:

    public string GetMessage(params object[] otherValues) {
        if (otherValues == null) return string.Format(this.Message, this.FirstValue);
    
        switch (otherValues.Length)
        {
            case 0:
                return string.Format(this.Message, this.FirstValue);
            case 1:
                return string.Format(this.Message, this.FirstValue, otherValues[0]);
            case 2:
                return string.Format(this.Message, this.FirstValue, otherValues[0], otherValues[1]);
            default:
                return string.Format(this.Message, new[] { this.FirstValue }.Concat(otherValues).ToArray()); 
        }
    }
    

    【讨论】:

      【解决方案4】:

      预处理消息

      如果您不想在每个 GetMessage(...) 调用中创建一个新数组,您可以插入 FirstValue消息在开头一次。然后GetMessage(...) 只使用string.Format(...)otherValues 参数。

      Message 属性在 FirstValue 设置后初始化一次,例如在构造函数或 init 方法中,如下所示:

      void InitMessage()
      {
          Message = String.Format(Message, FirstValue, "{0}", "{1}", "{2}", "{3}", "{4}");
      }
      

      InitMessage 方法用 FirstValue 初始化 Message 中的第一个索引,用“{index}”初始化其余索引,即“{0 }", "{1}", "{2}",... (允许有比消息索引更多的params 元素)。

      现在 GetMessage 可以调用 String.Format 而无需像这样的任何数组操作:

      public string GetMessage(params object[] otherValues)
      {
        return String.Format(Message, otherValues);
      }
      

      示例:

      假定以下属性值:
      this.Message = "First value is '{0}'. Other values are '{1}' and '{2}'."this.FirstValue = "blue"

      InitMessageMessage 更改为:
      "First value is 'blue'. Other values are '{0}' and '{1}'."

      GetMessage 调用
      GetMessage("green", "red")

      结果
      "First value is 'blue'. Other values are 'green' and 'red'."

      【讨论】:

      • @brernder:有趣的方法。在其他问题中可能有用。但是当您使用 Concat() 时,它似乎需要更多的工作,因为在 Format 中直接使用 Concat() 也应该可以解决它。
      • 你是对的。我已经通过在 InitMessage 方法中将“{...}”参数添加到 String.Format 调用来更新答案。
      【解决方案5】:

      如果您确实无法为数组创建另一个结构,则另一种混乱的方法是使用 RegEx 破解格式。

      private string FormatEval(Match m)
      {
          int val = -1;
          string formatted = m.Value;
          if (int.TryParse(m.Groups["index"].Value, out val))
              formatted = val == 0 ? this.FirstValue : "{" + (val - 1).ToString() + "}";
          return formatted;
      }
      
      public string GetMessage(params object[] otherValues)
      {
          string format = Regex.Replace(this.Message, @"\{(?<index>\d+)\}", FormatEval);
          return string.Format(format, otherValues);
      }
      

      基本上只解析格式化标记({0}、{1})等的格式字符串。 并减少他们的指数。如果令牌最初是 {0},请将其替换为 this.FirstName 字符串。

      本质上,这是手动执行 String.Format 的第一步,然后将生成的字符串传递给 REAL String.Format 方法以完成。

      【讨论】:

        【解决方案6】:

        传递离散元素

        为了避免在everey GetMessage 调用中创建数组,您可以通过其离散元素传递otherValues

        public string GetMessage(params object[] otherValues)
        {
          return String.Format(Message,
                               FirstValue,
                               GetOrDefault(otherValues, 0),
                               GetOrDefault(otherValues, 1),
                               GetOrDefault(otherValues, 2),
                               GetOrDefault(otherValues, 3),
                               GetOrDefault(otherValues, 4));
        }
        
        private object GetOrDefault(object[] otherValues, int index)
        {
          if (otherValues == null)
            return null;
        
          if (index < otherValues.Length)
            return otherValues[index];
        
          return null;
        }
        

        【讨论】:

          猜你喜欢
          • 2013-09-24
          • 1970-01-01
          • 2016-06-16
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-04-30
          相关资源
          最近更新 更多