Syl*_*gue 16 c# compiler-construction struct
我只是遇到了一些非常奇怪的东西:当你在一个值类型上使用Equals()方法时(如果这个方法当然没有被覆盖)你会得到一些非常慢的东西- 使用一对一比较字段反思!如:
public struct MyStruct{
int i;
}
(...)
MyStruct s, t;
s.i = 0;
t.i = 1;
if ( s.Equals( t )) /* s.i will be compared to t.i via reflection here. */
(...)
Run Code Online (Sandbox Code Playgroud)
我的问题:为什么C#编译器不生成比较值类型的简单方法?像(在MyStruct的定义中):
public override bool Equals( Object o ){
if ( this.i == o.i )
return true;
else
return false;
}
Run Code Online (Sandbox Code Playgroud)
编译器在编译时知道MyStruct的字段是什么,为什么它要等到运行时才能枚举MyStruct字段?
对我来说很奇怪.
谢谢 :)
补充:对不起,我只是意识到,当然,Equals它不是语言关键字而是运行时方法......编译器完全不知道这种方法.所以在这里使用反射是有意义的.
Meh*_*ari 10
它不使用反射时,它并不需要.它只是逐位比较值,struct如果它可以这样做.但是,如果任何struct成员(或成员的成员,任何后代)覆盖object.Equals并提供其自己的实现,显然,它不能依赖于逐位比较来计算返回值.
它变慢的原因是必须将Equals类型object和值类型的参数设置为框,以将其视为object.拳击涉及在堆上分配内存和将值类型复制到该位置的内存.
您可以手动为Equals方法提供重载,该方法将您自己的struct参数作为参数来阻止装箱:
public bool Equals(MyStruct obj) {
return obj.i == i;
}
Run Code Online (Sandbox Code Playgroud)
sna*_*arf 10
以下是mscorlib中反编译的ValueType.Equals方法:
public override bool Equals(object obj)
{
if (obj == null)
{
return false;
}
RuntimeType type = (RuntimeType) base.GetType();
RuntimeType type2 = (RuntimeType) obj.GetType();
if (type2 != type)
{
return false;
}
object a = this;
if (CanCompareBits(this))
{
return FastEqualsCheck(a, obj);
}
FieldInfo[] fields = type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance);
for (int i = 0; i < fields.Length; i++)
{
object obj3 = ((RtFieldInfo) fields[i]).InternalGetValue(a, false);
object obj4 = ((RtFieldInfo) fields[i]).InternalGetValue(obj, false);
if (obj3 == null)
{
if (obj4 != null)
{
return false;
}
}
else if (!obj3.Equals(obj4))
{
return false;
}
}
return true;
}
Run Code Online (Sandbox Code Playgroud)
如果可能的话,将进行逐位比较(注意CanCompareBits和FastEqualsCheck,两者都被定义为InternalCall.JIT可能会在这里注入适当的代码.至于它为什么这么慢,我不能告诉你.
| 归档时间: |
|
| 查看次数: |
6782 次 |
| 最近记录: |