字符串插值中的 lambda 表达式

lambda expressions in string interpolation

我正在尝试在字符串插值中使用 lambda 表达式,方法是:

var sb = new StringBuilder();
var a = $@"test { () => {
    var sb = new StringBuilder();
    foreach (var v in new string[] { "abc", "def", "ghi" })
        sb.Append(v);
    return sb.ToString();
}} test";
var b = $@"test {F1()} test";

Console.WriteLine(a);
Console.WriteLine(b);

string F1()
{
    var sb = new StringBuilder();
    foreach (var v in new string[] { "abc", "def", "ghi" })
        sb.Append(v);
    return sb.ToString();
}

这给出了以下输出:

test System.Func`1[System.String] test
test abcdefghi test

实际用例更复杂:我有一个包含 html 格式的邮件正文的字符串,我需要在几个地方插入几行 table 行。 我认为在 lambda 表达式中放置 forach 循环是个好主意:我发现这样的结果非常易读。

不幸的是,我看到 c# 在表达式上调用 ToString(),而不是返回表达式值本身。

如果我调用外部函数,则不会发生这种情况。

I see that c# invokes ToString() on the expression

是的,因为它将委托视为对象,并且在理解如何处理对象方面缺少任何更具体的内容,所以它只是在其上调用 ToString()。

你的两次尝试之间有一个关键的区别,如果我把委托拉出来可能会更清楚:


var f = () => {
    var sb = new StringBuilder();
    foreach (var v in new string[] { "abc", "def", "ghi" })
        sb.Append(v);
    return sb.ToString();
};
        
var a = $@"test {f} test";
var b = $@"test {F1()} test";

var c = $@"test {f()} test";

F1 被调用是因为它由 () 执行并且其返回结果包含在字符串中。 f 没有被调用,所以 f 本身是什么 成为包含在字符串中的东西

var c 版本如您所料工作..(在我看来,这是一种更简洁的结构方式;本地函数也可以清理它)

在这种特殊情况下,您可能还想考虑:

var d = $@"test {new[]{"abc","def","ghi"}.Concat()} test"