【问题标题】:String.Format parameter order annoyanceString.Format 参数顺序烦人
【发布时间】:2009-09-15 11:34:26
【问题描述】:

C# 似乎强迫你显式命名 String.Format 中每个参数的索引,这真的很烦人,如果你想在某个地方添加另一个参数,你要么必须重新索引字符串,要么将新参数放在末尾.

有没有办法让 C# 自动执行此操作?

例如(我知道这是毫无意义的学究,这只是一个例子:)

我开始:

String.Format("{0} {1} {1} {2} {3}", a, b, c, d)

如果我想在开头添加一个参数,我可以执行以下操作之一:

String.Format("{4} {0} {1} {1} {2} {3}", a, b, c, d, e)
String.Format("{0} {1} {2} {2} {3} {4}", e, a, b, c, d)

例如,在 Delphi 中,我可以这样做:

String.Format("{} {} {} {2} {} {}", e, a, b, c, d)

【问题讨论】:

  • C# 和 delphi 中的两行是否返回相同的内容?

标签: c# string formatting


【解决方案1】:

嗯,C# 中没有任何东西可以自动为您执行此操作。您总是可以编写自己的方法来做到这一点,但坦率地说,我发现它的可读性较差。与上一条相比,要了解您的最后一行所做的事情,需要做更多的思考(IMO)。当您点击{2} 时,您必须在心理上回溯并将上一项替换为{3} 以跳过{2} 等。

就我个人而言,我更喜欢输入时间较长但阅读清晰的代码。

【讨论】:

  • +1:在最初写作时,可维护性应始终胜过一次性节省。
  • +1 "计算机程序应设计为供人类阅读并由计算机偶然运行"
  • String.Format("{a} {b} {b} {c} {d}", a, b, c, d) 怎么样?这可以添加到 .NET 4.0 中吗?也许编译器可以提供帮助。还是新的 DLR?我可能在这里遗漏了一些东西,但它会很好......
  • 恕我直言,可读性通过将参数放在下一行来解决。
  • @Jamie:这根本不能解决可读性问题。哪个参数对应哪个替换标记并没有更清楚。
【解决方案2】:

从 Visual Studio 2015 开始,您可以使用 Interpolated Strings 绕过此问题(它是一个编译器技巧,因此您定位的 .net 框架版本无关紧要)。

然后代码看起来像这样

string txt = $"{person.ForeName} is not at home {person.Something}"; 

我认为它使代码更具可读性并且不易出错。

【讨论】:

    【解决方案3】:

    您请求的功能不是框架的一部分。这是我发现的一个很好的扩展方法,它提供了命名参数 c#。我认为 Marc Gravell 发布了它或其他 SO 大师之一。

            static readonly Regex rePattern = new Regex(@"\{([^\}]+)\}", RegexOptions.Compiled);
    
    
        /// <summary>
        /// Shortcut for string.Format. Format string uses named parameters like {name}.
        /// 
        /// Example: 
        /// string s = Format("{age} years old, last name is {name} ", new {age = 18, name = "Foo"});
        ///
        /// </summary>
        /// <param name="format"></param>
        /// <param name="values"></param>
        /// <returns></returns>
        public static string FN<T>(this string pattern, T template)
        {
            Dictionary<string, string> cache = new Dictionary<string, string>();
            return rePattern.Replace(pattern, match =>
            {
                string key = match.Groups[1].Value;
                string value;
    
                if (!cache.TryGetValue(key, out value))
                {
                    var prop = typeof(T).GetProperty(key);
                    if (prop == null)
                    {
                        throw new ArgumentException("Not found: " + key, "pattern");
                    }
                    value = Convert.ToString(prop.GetValue(template, null));
                    cache.Add(key, value);
                }
                return value;
            });
        }
    

    【讨论】:

      【解决方案4】:

      尽管 C# 不能为您做到这一点,但该工具可以在这里提供帮助。

      例如,如果字符串中的参数多于字符串后面的参数,Resharper 会向您发出警告。我查看了是否支持 Resharper 中的参数重新排序,但在这种情况下不支持(R# 支持更改方法签名,但这在这里没有帮助)。

      看看 DevEx 的 Code Rush。该工具很可能满足您的需求。

      【讨论】:

        【解决方案5】:

        我知道这已经过时了,我同意 Jon 的观点。即使使用大格式字符串(参见下面的代码示例),如果我必须添加一些东西,我仍然只需要不到 1 分钟的时间来重做项目的索引位置,而且我发现它更易于维护和阅读,然后尝试创建一个使过程自动化的方法。自动化的问题是几周后我尝试查看代码时..您不能一眼就看出来。此外,一旦您很好地学习了 Visual Studio 并学会使用诸如块编辑模式和其他一些高级功能之类的东西,您的工作效率就会很高。

        //-----------------------------------------------------------------------------
        // <copyright file="ShellForm.cs" company="DCOM Productions">
        //     Copyright (c) DCOM Productions.  All rights reserved.
        // </copyright>
        //-----------------------------------------------------------------------------
        
        string updateCommandText = string.Format("UPDATE `moh`.`moh` SET ageact = '{0}', branch = '{1}', cemetary = '{2}', citation = '{3}', citycement = '{4}', cdateact = '{5}', cdateaward = '{6}', cdatebirth = '{7}', cdatedeath = '{8}', namefirst = '{9}', namelast = '{10}', placeact = '{11}', placeenter = '{12}', presat = '{13}', presby = '{14}', rankact = '{15}', rankawd = '{16}', rankhigh = '{17}', synopsis = '{18}', unit = '{19}', war = '{20}', imgfile = '{21}' WHERE ID = '{22}'",
            /* {0}  */ uxAgeAct.Text.Replace("'", "''"),
            /* {1}  */ uxBranch.Text.Replace("'", "''"),
            /* {2}  */ uxCemetary.Text.Replace("'", "''"),
            /* {3}  */ uxCitation.Text.Replace("'", "''"),
            /* {4}  */ uxCityCemetary.Text.Replace("'", "''"),
            /* {5}  */ uxDateAct.Text.Replace("'", "''"),
            /* {6}  */ uxDateAward.Text.Replace("'", "''"),
            /* {7}  */ uxDateBirth.Text.Replace("'", "''"),
            /* {8}  */ uxDateDiceased.Text.Replace("'", "''"),
            /* {9}  */ uxNameFirst.Text.Replace("'", "''"),
            /* {10} */ uxNameLast.Text.Replace("'", "''"),
            /* {11} */ uxPlaceAct.Text.Replace("'", "''"),
            /* {12} */ uxPlaceEnter.Text.Replace("'", "''"),
            /* {13} */ uxPresentedAt.Text.Replace("'", "''"),
            /* {14} */ uxPresentedBy.Text.Replace("'", "''"),
            /* {15} */ uxRankAct.Text.Replace("'", "''"),
            /* {16} */ uxRankAwarded.Text.Replace("'", "''"),
            /* {17} */ uxRankHigh.Text.Replace("'", "''"),
            /* {18} */ uxSynopsis.Text.Replace("'", "''"),
            /* {19} */ uxUnit.Text.Replace("'", "''"),
            /* {20} */ uxWar.Text.Replace("'", "''"),
            /* {21} */ uxImgFile.Text.Replace("'", "''"),
            /* {22} */ dataRow["ID"].ToString());
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2013-09-24
          • 2010-11-28
          • 1970-01-01
          • 2014-05-04
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多