1

.NET Framework 3.5 を使用してMethodBaseインスタンスをメソッドと比較すると、非常に奇妙な動作が発生します。コンパイラで定義されたコンストラクター メソッド オブジェクトとオープン ジェネリック メソッド オブジェクトを比較すると失敗します。EqualsNullReferenceException

再現コードは次のとおりです。

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 では、nullnull の可能性があるruntimeMethodInfo変数を使用する前に -check が移動されました。私にとって、3.5 の動作はフレームワークのバグのようですね。

問題は、これらのオブジェクトを安全に比較するための回避策または方法があるかどうかです。実際のコードでは、Equals直接呼び出すのではなく、コレクションなどのどこかで暗黙的に使用しているため、キャッチNullReferenceExceptionsはうまく聞こえないことに注意してください。

4

1 に答える 1

1

Equals代替メソッドを作成する以外に、適切な回避策があるようには見えません。または、少なくともctorランタイムのEqualsメソッドを呼び出す前に値をチェックするもの。

コレクションに対して、EqualityComparerカスタム比較を行うための を作成します。Equalsこれにより、デフォルトメソッドの呼び出しがなくなります。

于 2013-01-14T12:07:18.503 に答える