System.Reflection.RuntimeMethodInfo.Equals在.NET 3.5中失败并显示NullReferenceException

时间:2013-01-13 13:19:38

标签: .net nullreferenceexception system.reflection

在使用.NET Framework 3.5比较MethodBase实例和Equals方法时,我遇到了一个非常奇怪的行为 - 在比较编译器定义的构造函数方法时,它只是失败了NullReferenceException具有开放泛型方法对象的对象。

这是repro代码:

class TheClass
{
    public T TheMethod<T>()
    {
        return default(T);
    }
}

class Program
{
    private static void Main(string[] args)
    {
        var ctor = typeof(TheClass).GetConstructors().Single();
        var generic = typeof(TheClass).GetMethods().Single(x => x.Name == "TheMethod");

        Console.WriteLine(generic.Name); // TheMethod
        Console.WriteLine(generic.GetType().Name); // RuntimeMethodInfo

        Console.WriteLine(ctor.Name); // .ctor
        Console.WriteLine(ctor.GetType().Name); // RuntimeConstructorInfo

        Console.WriteLine(generic.Equals(ctor)); // throws NullReferenceException
        Console.ReadKey();
    }
}

它在.NET 4.0中运行良好。 我使用反编译器研究了3.5和4.0中的RuntimeMethodInfo.Equals实现,这是有趣的部分:

.NET 3.5

if (!this.IsGenericMethod)
    return obj == this;
  RuntimeMethodInfo runtimeMethodInfo = obj as RuntimeMethodInfo;
  if (this.GetMethodHandle().StripMethodInstantiation() != runtimeMethodInfo.GetMethodHandle().StripMethodInstantiation() || runtimeMethodInfo == null || !runtimeMethodInfo.IsGenericMethod)
    return false;
// ...

.NET 4.0

  if (!this.IsGenericMethod)
    return obj == this;
  RuntimeMethodInfo runtimeMethodInfo = obj as RuntimeMethodInfo;
  if ((MethodInfo) runtimeMethodInfo == (MethodInfo) null || !runtimeMethodInfo.IsGenericMethod || RuntimeMethodHandle.StripMethodInstantiation((IRuntimeMethodInfo) this).Value.Value != RuntimeMethodHandle.StripMethodInstantiation((IRuntimeMethodInfo) runtimeMethodInfo).Value.Value)
    return false;

在.NET 4.0中,null - 在使用可能为空的runtimeMethodInfo变量之前移动了检查。对我来说,3.5行为似乎是一个框架错误,不是吗?

所以问题是 - 是否有解决方法或安全地比较这些对象的方法?请注意,在实际代码中,我不是直接调用Equals,而是在集合等中隐式使用它,因此捕获NullReferenceExceptions听起来不太好。

1 个答案:

答案 0 :(得分:1)

除了编写替换Equals方法之外,看起来不是一个好的解决方法。或者至少在调用运行时的ctor方法之前检查Equals值的内容。

对于集合,创建EqualityComparer以进行自定义比较。这将消除对默认Equals方法的调用。