使用C#6中的命名参数进行字符串插值

时间:2016-04-20 13:20:28

标签: c# asp.net asp.net-mvc

鉴于我有一个存储在我的数据库中的元数据资源字符串将返回如下:

var pageTitle = "Shop the latest {category1} Designer {category2} {category3} at www.abc.com";

我希望将{placeholders}替换为变量values;

var category1 = "womenswear";
var category2 = "dresses";
var category3 = "cocktail dresses";

我试过,没有运气;

var newTitle = $"pageTitle, category1, category2, category3";
var newTitle = $(pageTitle, category1, category2, category3);

我知道我可以使用具有性能开销的string.Replace()。有谁知道如何使用最新的C#字符串插值有效地完成这项工作?

5 个答案:

答案 0 :(得分:19)

您无法在此处使用字符串插值。字符串插值是string.Format的编译时重写方法,这是您应该使用的解决方案:

var newTitle = string.Format("{0}, {1}, {2}, {3}", pageTitle, category1, category2, category3);

string.Join

var newTitle - string.Join(", ", new string[] { pageTitle, category1, category2, category3 });

由于您是从数据库加载的,因此继续使用string.Replace可能会更好。

答案 1 :(得分:18)

  

我知道我可以使用性能开销

的string.Replace()

仅为纳秒。你不应该过早地进行优化。

如上所述,C#6字符串插值功能在编译时发生。如果要在运行时执行此操作,则必须使用字符串替换。

我认为你的字符串格式是这样的,以便于编辑,没有固定的替换顺序,所以只需这样做:

var input = "Shop the latest {category1} Designer {category2} {category3} at www.abc.com";
var category1 = "womenswear";
var category2 = "dresses";
var category3 = "cocktail dresses";

var result = input.Replace("{category1}", category1)
                  .Replace("{category2}", category2)
                  .Replace("{category3}", category3);

这将起作用。您还可以将替换值存储在字典中,并循环键以使用值替换键。

答案 2 :(得分:8)

尽管.NET没有为此提供内置功能,但您可以使用正则表达式轻松构建一个非常好的实现:

public static string Format(string formatWithNames, IDictionary<string,object> data) {
    int pos = 0;
    var args = new List<object>();
    var fmt = Regex.Replace(
        formatWithNames
    ,   @"(?<={)[^}]+(?=})"
    ,   new MatchEvaluator(m => {
            var res = (pos++).ToString();
            var tok = m.Groups[0].Value.Split(':');
            args.Add(data[tok[0]]);
            return tok.Length == 2 ? res+":"+tok[1] : res;
        })
    );
    return string.Format(fmt, args.ToArray());
}

想法是用连续数字替换名称(参见sb.Append(pos++)),构建一个对象参数数组(参见args.Add(data[tok[0]])),并将结果传递给string.Format以使用{{ 1}}的格式化功能。

现在,您可以将资源传递给此string,以及键值对字典,并获取使用.NET内置格式化功能格式化的字符串:

Format

请注意,字符串文字前面没有var x = new Dictionary<string,object> { {"brown", 1} , {"jumps", 21} , {"lazy", 42} }; Console.WriteLine("{0}", Format("Quick {brown} fox {jumps:C} over the {lazy:P} dog", x)); ,所以这里没有C#的内置插值。

打印

$

该方法基于idea by Scott Hanselman,但格式化方式不同。

Demo.

答案 3 :(得分:5)

如果您不想使用字符串替换,则需要使用原始格式语法:

var pageTitle = "Shop the latest {0} Designer {1} {2} at www.abc.com";

var category1 = "womenswear";
var category2 = "dresses";
var category3 = "cocktail dresses";

var newTitle = string.Format(pageTitle, category1, category2, category3);

或在变量之后放置格式化字符串

var category1 = "womenswear";
var category2 = "dresses";
var category3 = "cocktail dresses";

var newTitle = $"Shop the latest {0} Designer {0} {0} at www.abc.com";

字符串插值在编译时转换为string.Format调用,因此无法在运行时使格式化字符串成为变量。

答案 4 :(得分:0)

请查看我的库,它解决了这个问题TinyTools如果你使用它并且喜欢它留下一个星。

    var person = new Person
    {
        FirstName = "John",
        LastName = "Smith"
    };
    var template = "Hello world, I'm {FirstName} {LastName}";

    var result = template.Interpolate(person);
    result.ShouldBe("Hello world, I'm John Smith");