0

リフレクションを使用して、タイプの 2 つの異なるが「等しい」インスタンスで .Equals を呼び出した結果を判断しようとしています。

私の方法は次のようになります。

public static bool TypeComparesProperties(Type t)
{
    // return true if (an instance of t).Equals(a different instance of t)
    //  will be true if all publicly accessible properties of the instances
    //  are the same
}

例として:

string a = "Test";
string b = "Test";
bool areEqual = a.Equals(b);   // areEqual will be true
// so:
TypeComparesProperties(typeof(string));   // should return true

ただし、与えられた:

public class MyComplexType
{
    public int Id { get; set; }
    public string MyString { get; set; }
}

MyComplexType a = new MyComplexType {Id = 1, MyString = "Test"};
MyComplexType b = new MyComplexType { Id = 1, MyString = "Test" };
bool areEqual = a.Equals(b);   // areEqual will be false
// so:
TypeComparesProperties(typeof(MyComplexType));   // should return false

次のようにクラスに実装IEquatable<MyComplexType>すると、代わりに true になります。

public class MyComplexType : IEquatable<MyComplexType>
{
    public int Id { get; set; }
    public string MyString { get; set; }

    public bool Equals(MyComplexType other)
    {
        return (Id.Equals(other.Id) && MyString.Equals(other.MyString));
    }
}

リフレクションを使用して 2 つのインスタンスをインスタンス化し、すべてのプロパティを適切に型指定された既定値に設定することで、おそらくそれを実行できると思います。しかし、それは多くの作業と多くのオーバーヘッドであり、型に空のコンストラクターがないと問題が発生すると思います。

他のアイデアはありますか?


編集:

人々は私の意図に混乱しているようです。謝罪します。うまくいけば、これが明確になるでしょう:

2 つのオブジェクトをその能力を最大限に比較するメソッドがあります。単純に .Equals() を呼び出すだけでは十分ではありません。

  1. オブジェクトは値型になるか、適切な方法で IEquatable を実装し、真の応答が得られます。すごい!
  2. オブジェクトはすべて同じプロパティを持ち、「等しい」場合がありますが、それらは異なるインスタンスであるため、誤った応答が返されます。 この false が、オブジェクトが「等しくない」ためなのか、それともインスタンスが異なるだけなのかはわかりません

したがって、私の考えでは、比較方法は次のようにする必要があります。

  1. Equalsオブジェクト タイプを調べて、そのメソッドが同じパブリック プロパティを持つ 2 つの異なるインスタンスに対して true を返すかどうかを確認します。
  2. その場合は、メソッドを呼び出してEquals結果を返します
  3. そうでない場合は、すべてのプロパティとフィールドを見て、できる限り比較して、それらが等しいかどうかを判断してください

ここで、手順 3 にスキップできることは理解していますが、必要かどうかを事前に判断する方法があれば、時間を節約できます。


編集2:

いくつかの理由でこれを閉じます。

  1. 話せば話すほど、自分が求めたことは自分が本当にやりたかったことではないことに気付く
  2. やりたいと思っても、近道はありません。以前の編集については、とにかくステップ 3 にスキップする必要があります。

ご意見をお寄せいただきありがとうございます。

4

3 に答える 3

1

正直なところ、valuetypes を比較する場合、デフォルトの equals で問題ありません。ただし、参照型で equals のデフォルトの実装を使用すると、動作が異なり、参照ポインターの等価性が高くなります。真のオブジェクト レベルの Equals 操作を機能させるには、IEquatable を実装するか、各クラスで Equals メソッドをオーバーライドするか、リフレクションを使用して各パブリック プロパティを比較する必要があります。このリンクを見てください。役立つ場合とそうでない場合があります。

SO - 内部 Equals オブジェクト

于 2009-12-04T03:38:45.137 に答える
1

この answerに基づいて何かを行うことができます。これは、フィールドではなくpublic propertiesを比較するものであり、必要なことは何でもできることに注意してEqualsください。代わりにフィールドを使用するように変更することは難しくありませんが、正直なところ、ここにあるドライバーが何であるかはわかりません。Equals(object)andEquals(MyComplexType)と use EqualityComparer<T>.Default.Equals(x,y)(これはIEquatable<T>、nullなどを処理しますNullable<T>-object.Equals(x,y)フォールバック戦略として使用します)。

あなたの最新のニーズを満たすと私が思うものについて:

public static bool AreEqual<T>(T x, T y) {
    if(ReferenceEquals(x,y)) return true;
    if(x==null || y == null) return false;
    IEquatable<T> eq = x as IEquatable<T>;
    if(eq == null) return PropertyCompare.Equal(x,y);
    return eq.Equals(y);
}
于 2009-12-04T05:57:12.367 に答える
1

サイズはこちらをご試着ください。

public static bool TypeComparesProperties(Type t)
{
    Type equatableInterface = typeof(IEquatable<>);

    if (t.GetInterface(equatableInterface.Name) != null)
    {
        return true;
    }
    else
    {
        Type objectClass = typeof(Object);
        MethodInfo equalsMethod = t.GetMethod("Equals", new Type[] { typeof(object) });

        return equalsMethod.DeclaringType != objectClass;
    }
}

IEquatable<>最初に、メソッドは型に実装されているかどうかを確認します。存在する場合は、true を返します。Equals(object)そうでない場合は、型がメソッドをオーバーライドしているかどうかを確認してください。ある場合は true を返します。それ以外の場合 (Equalsメソッドが で宣言された既定のメソッドである場合Object)、false を返します。

于 2009-12-04T04:06:16.307 に答える