MethodBase
在将实例与Equals
使用 .NET Framework 3.5 的方法进行比较时,我遇到了一个非常奇怪的行为——NullReferenceException
如果将编译器定义的构造函数方法对象与开放的泛型方法对象进行比较,它就会失败。
这是重现代码:
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 中运行良好。我已经RuntimeMethodInfo.Equals
使用反编译器研究了 3.5 和 4.0 中的实现,这是有趣的部分:
.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
之前移动了 -check 。runtimeMethodInfo
对我来说,3.5 的行为似乎是一个框架错误,不是吗?
所以问题是 -是否有解决方法或方法可以安全地比较这些对象?请注意,在实际代码中,我不是Equals
直接调用,而是在集合等的某个地方隐式使用它,所以捕获NullReferenceExceptions
听起来不太好。