C# - 值类型等于方法 - 为什么编译器使用反射?

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

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

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

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

对我来说很奇怪。

谢谢:)

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

最佳答案

以下是从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;
}

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

关于C# - 值类型等于方法 - 为什么编译器使用反射?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57544260/

相关文章:

c# - 如何获取另一个线程的 ThreadStatic 值?

c++ - VS2005 如何强制所有指针访问不对齐?

matlab - 一次分配多个字段的巧妙方法?

c# - If - else 没有 else 的语句

c# - 在 C# 中,是否可以模拟出 IMessageReceiver 和相关类进行单元测试?

c# - 如何使用 Ajax 在 ASP.NET MVC 上显示服务器端验证错误

javascript - 是否可以使用NODE.JS(或PYTHON)开发ACM ONLINE JUDGE系统?

haskell - 为什么 GHC 在脱糖之前要进行类型检查?

c - 为什么我的结构(在头文件中声明)在 gcc 编译的 c 文件中无法被识别?

c++ - 结构在单独的头文件中导致 C++ 中的问题