C#匿名类型'ToString'复杂吗?
有人知道为什么C中的匿名类型使用如此复杂的C#匿名类型'ToString'复杂吗?,c#,.net,.net-core,roslyn,anonymous-types,C#,.net,.net Core,Roslyn,Anonymous Types,有人知道为什么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;
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);
}
public重写字符串ToString(){
object[]数组=新对象[2];
j_uutpar val=i_u字段;
参考j_uutpar参考=参考值;
j_uutpar val2=默认值(j_utpar);
对象对象对象;
if(val2==null){
val2=参考;
参考=参考值2;
if(val2==null){
obj=null;
goto IL_0046;
}
}
obj=reference.ToString();
goto IL_0046;
IL_0046:
数组[0]=obj;
j_uutpar val3=i_u字段;
参考j_u_utpar reference2=参考值3;
j_uutpar val4=默认值(j_utpar);
对象obj2;
if(val4==null){
val4=参考2;
参考2=参考值4;
if(val4==null){
obj2=null;
goto IL_0081;
}
}
obj2=reference2.ToString();
goto IL_0081;
IL_0081:
数组[1]=obj2;
返回string.Format(null,“{a={0},b={1}”,数组);
}
查看Roslyn编译器从一开始就通过string.Format
实现。我不知道为什么它是以这种方式实现的。因为它是编译器,所以我假设性能和可维护性的原因已经考虑在内(而不是生成代码的简单性)。虽然Format内部似乎使用了StringBuilder
,但不会说以前的实现较慢或较快
UPD
似乎在Roslyn
引入之前,编译器真正生成了StrinBuilder
实现。来自Andrew Troelsen的Pro C#2008和.NET 3.5平台:
所有匿名类型都自动从System.Object派生,并随重写版本的Equals()、GetHashCode()和ToString()一起提供。ToString()实现只是从每个名称/值对构建一个字符串,例如:
public重写字符串ToString()
{
StringBuilder=新建StringBuilder();builder.Append(“{Color=”);
builder.Append(这个.i__字段);builder.Append(“,Make=”);
builder.Append(此.i__字段);builder.Append(“,CurrentSpeed=”);
builder.Append(这个.i__字段);builder.Append(“}”);
返回builder.ToString();
}
我已经写过(不知道它有多正确=),而且旧的实现似乎更快
在github()上还发现了一个问题,除其他事项外,它引起了人们对ToString
性能的关注,但在评论中提出了一个有效的问题:
对ToString表示使用匿名类型是否常见?我怀疑大多数人会不会打电话给ToString来了解其中一个。它们将被传递给序列化程序,序列化程序将执行不同的表示或用作LINQ中的分组键
我强烈不同意这是基于意见的,但这对你来说是多余的。有人知道所讨论的实际情况,甚至可能会有Github问题解释或提交来解释更改……每当
?。
运算符应用于无约束类型参数时,C#编译器就会生成带有ref赋值的奇怪代码模式@Daniel谢谢,但我想知道这个模式的理由是什么。由于问题不幸地结束了,我将给你一个接近正确的答案。我确实看到了github的问题,但我认为这与为什么ToString
变得如此复杂无关,尽管我开始相信这可能是为了最小化装箱和/或帮助JIT在运行时为具体类型构造方法时进行优化。顺便说一句,你所说的“责备”是什么意思?@NetMage谢谢。简单的怪罪。
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();
}