C# - 值类型等于方法 - 为什么编译器使用反射? [英] C# - Value Type Equals method - why does the compiler use reflection?

查看:19
本文介绍了C# - 值类型等于方法 - 为什么编译器使用反射?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚遇到了一些对我来说很奇怪的事情:当你在一个值类型上使用 Equals() 方法时(当然,如果这个方法没有被覆盖)你会得到一些非常慢 - 使用反射对字段进行一对一比较!如:

I just came across something pretty weird to me : when you use the Equals() method on a value type (and if this method has not been overriden, of course) you get something very very slow -- fields are compared one to one using reflection ! As in :

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. */
      (...)

我的问题:为什么 C# 编译器不生成一个简单的方法来比较值类型?类似于(在 MyStruct 的定义中):

My question : why does the C# compiler do not generate a simple method to compare value types ? Something like (in MyStruct's definition) :

   public override bool Equals( Object o ){
      if ( this.i == o.i )
         return true;
      else
         return false;
   }

编译器在编译时就知道MyStruct的字段是什么,为什么要等到运行时才枚举MyStruct的字段?

The compiler knows what are the fields of MyStruct at compile time, why does it wait until runtime to enumerate MyStruct fields ?

对我来说很奇怪.

谢谢:)

ADDED : 抱歉,我才意识到,当然,Equals 不是语言关键字,而是运行时方法……编译器完全不知道这个方法.所以在这里使用反射是有意义的.

ADDED : Sorry, I just realize that, of course, Equals is not a language keyword but a runtime method... The compiler is completely unaware of this method. So it make sens here to use reflection.

推荐答案

以下是来自 mscorlib 的反编译 ValueType.Equals 方法:

The following is the decompiled ValueType.Equals method from mscorlib:

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;
}

如果可能,将进行逐位比较(注意 CanCompareBits 和 FastEqualsCheck,两者都定义为 InternalCall.JIT 大概会在此处注入适当的代码.至于为什么它这么慢,我不能'不告诉你.

When possible, a bit-wise comparison will be done (note the CanCompareBits and FastEqualsCheck, both of which are defined as InternalCall. The JIT would presumably inject the appropriate code here. As to why it is so slow, I couldn't tell you.

这篇关于C# - 值类型等于方法 - 为什么编译器使用反射?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆