.NET Framework 3.5 を使用してMethodBase
インスタンスをメソッドと比較すると、非常に奇妙な動作が発生します。コンパイラで定義されたコンストラクター メソッド オブジェクトとオープン ジェネリック メソッド オブジェクトを比較すると失敗します。Equals
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
null の可能性があるruntimeMethodInfo
変数を使用する前に -check が移動されました。私にとって、3.5 の動作はフレームワークのバグのようですね。
問題は、これらのオブジェクトを安全に比較するための回避策または方法があるかどうかです。実際のコードでは、Equals
直接呼び出すのではなく、コレクションなどのどこかで暗黙的に使用しているため、キャッチNullReferenceExceptions
はうまく聞こえないことに注意してください。