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.
有谁知道为什么 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.