C# 匿名类型 `ToString` 复杂吗?

C# Anonymous type `ToString` complicated?

有谁知道为什么 C# 中的匿名类型对 ToString 使用如此复杂的实现?我相信早期版本使用了更简单的 StringBuilder 实现。

这是来自 ILSpy 的示例 ToString

public override string ToString() {
    object[] array = new object[2];
    <a>j__TPar val = <a>i__Field;
    ref <a>j__TPar reference = ref val;
    <a>j__TPar val2 = default(<a>j__TPar);
    object obj;
    if (val2 == null) {
        val2 = reference;
        reference = ref val2;
        if (val2 == null) {
            obj = null;
            goto IL_0046;
        }
    }
    obj = reference.ToString();
    goto IL_0046;
    IL_0046:
    array[0] = obj;
    <b>j__TPar val3 = <b>i__Field;
    ref <b>j__TPar reference2 = ref val3;
    <b>j__TPar val4 = default(<b>j__TPar);
    object obj2;
    if (val4 == null) {
        val4 = reference2;
        reference2 = ref val4;
        if (val4 == null) {
            obj2 = null;
            goto IL_0081;
        }
    }
    obj2 = reference2.ToString();
    goto IL_0081;
    IL_0081:
    array[1] = obj2;
    return string.Format(null, "{{ a = {0}, b = {1} }}", array);
}

查看 blame of AnonymousTypeMethodBodySynthesizer.AnonymousTypeToStringMethodSymbol 似乎从一开始就通过 string.Format 为 Roslyn 编译器实现。为什么以这种方式实施我不知道。因为它是编译器,所以我假设考虑了性能和可维护性的原因(而不是生成代码的简单性)。不会说以前的实现速度较慢或更快,因为 string.Format 在内部似乎使用 StringBuilder 和一些缓存魔法。

UPD

似乎在引入Roslyn之前编译器真的生成了StrinBuilder实现。来自 Pro C# 2008 和 .NET 3.5 平台,作者:Andrew Troelsen:

All anonymous types automatically derive from System.Object and are provided with an overridden version of Equals(), GetHashCode(), and ToString(). The ToString() implementation simply builds a string from each name/value pair, for example:

public override string ToString()
{
    StringBuilder builder = new StringBuilder(); builder.Append("{ Color = "); 
    builder.Append(this.<Color>i__Field); builder.Append(", Make = "); 
    builder.Append(this.<Make>i__Field); builder.Append(", CurrentSpeed = "); 
    builder.Append(this.<CurrentSpeed>i__Field); builder.Append(" }");
    return builder.ToString();
}

我已经写了 small benchmark(虽然不确定它有多正确 =),但似乎旧的实现速度更快。

还在 github(Generate more efficient anonymous type members) 上发现了问题,除其他外引起了对 ToString 性能的关注,但在评论中提出了有效的问题:

Is it common to use anonymous types for their ToString representation? I doubt most people will ever call ToString on one of these. They will be passed to a serializer which will do a different representation or be used as a grouping key in LINQ.