3

現在、私はこれを持っています(アドバイスを読んだ後に編集しました):

struct Pair<T, K> : IEqualityComparer<Pair<T, K>>
{
    readonly private T _first;
    readonly private K _second;

    public Pair(T first, K second)
    {
        _first = first;
        _second = second;

    }

    public T First { get { return _first; } }
    public K Second { get { return _second; } }

    #region IEqualityComparer<Pair<T,K>> Members

    public bool Equals(Pair<T, K> x, Pair<T, K> y)
    {
        return x.GetHashCode(x) == y.GetHashCode(y);
    }

    public int GetHashCode(Pair<T, K> obj)
    {
        int hashCode = obj.First == null ? 0 : obj._first.GetHashCode();

        hashCode ^= obj.Second == null ? 0 : obj._second.GetHashCode();

        return hashCode;
    }

    #endregion

    public override int GetHashCode()
    {
        return this.GetHashCode(this);
    }

    public override bool Equals(object obj)
    {
        return (obj != null) && 
    (obj is Pair<T, K>) && 
    this.Equals(this, (Pair<T, K>) obj);
    }
}

問題は、 First と Second が参照型ではない可能性があることです (VS は実際にこれについて警告します) が、コードはまだコンパイルされます。それらを比較する前に、それら (First と Second) をオブジェクトにキャストする必要がありますか、またはこれを行うより良い方法はありますか?

編集:この構造体が値と参照型をサポートするようにしたいことに注意してください(つまり、クラスによる制約は有効な解決策ではありません)

編集2:私が達成しようとしていることに関しては、これを辞書で機能させたいと思っています。第二に、SRP はこの問題の本質ではないので、今のところ私にとって重要ではありません。後でいつでもリファクタリングできます。第 3 に、default(T) との比較は、null との比較の代わりに機能しません。試してみてください。

4

7 に答える 7

3

IEqualityComparer の実装は別のクラスにする必要があります (参照を再利用したいので、間違いなく構造体ではありません)。

また、構造体のデフォルトの GetHashcode 実装 (オーバーライドしない) はそのメンバーを考慮に入れるため、ハッシュコードは決してキャッシュしないでください。

于 2008-09-23T12:56:43.737 に答える
2

代わりに IEquatable が必要なようです:

internal struct Pair<T, K> : IEquatable<Pair<T, K>>
{
  private readonly T _first;
  private readonly K _second;

  public Pair(T first, K second)
  {
    _first = first;
    _second = second;
  }

  public T First
  {
    get { return _first; }
  }

  public K Second
  {
    get { return _second; }
  }

  public bool Equals(Pair<T, K> obj)
  {
    return Equals(obj._first, _first) && Equals(obj._second, _second);
  }

  public override bool Equals(object obj)
  {
    return obj is Pair<T, K> && Equals((Pair<T, K>) obj);
  }

  public override int GetHashCode()
  {
    unchecked
    {
      return (_first != null ? _first.GetHashCode() * 397 : 0) ^ (_second != null ? _second.GetHashCode() : 0);
    }
  }
}
于 2008-09-23T15:14:47.803 に答える
2

メソッドの比較でハッシュコードを使用する場合、ハッシュコードが同じかどうか「実際の値」を確認する必要があります。

bool result = ( x._hashCode == y._hashCode );
if ( result ) { result = ( x._first == y._first && x._second == y._second ); }
// OR?: if ( result ) { result = object.Equals( x._first, y._first ) && object.Equals( x._second, y._second ); }
// OR?: if ( result ) { result = object.ReferenceEquals( x._first, y._first ) && object.Equals( x._second, y._second ); }
return result;

しかし、「_first」フィールドと「_second」フィールドの比較には少し問題があります。デフォルトでは、参照型は「object.ReferenceEquals」メソッドを比較する前等値を使用しますが、オーバーライドできます。したがって、正しい解決策は、比較方法の「正確に何をすべきか」に依存します。「_first」および「_second」フィールドの「Equals」メソッド、または object.ReferenceEquals を使用する必要がありますか? それとももっと複雑ですか?

于 2008-09-23T13:03:05.093 に答える
0

警告に関しては、null の代わりに default(T) と default(K) を使用できます。

何を達成しようとしているのかわかりませんが、ハッシュコードを使用して同等性を比較するべきではありません.2つの異なるオブジェクトが同じハッシュコードを持たないという保証はありません. また、構造体は不変ですが、メンバー _first と _second はそうではありません。

于 2008-09-23T12:57:40.537 に答える
0

まず、このコードは SRP の原則に違反しています。アイテムの場合、ペアを保持するために使用されるペア クラスですよね? 同等性比較機能を委任するのは正しくありません。

次に、コードを見てみましょう。

引数の 1 つが null の場合、Equals メソッドは失敗します - 良くありません。Equals は Pair クラスのハッシュ コードを使用しますが、GetHashCode の定義を見てください。これはペア メンバーのハッシュ コードの組み合わせに過ぎず、項目の等価性とは関係ありません。Equals メソッドが実際のデータを比較することを期待します。残念ながら、現時点では忙しすぎて正しい実装を提供できません。しかし、一見すると、あなたのコードは間違っているようです。あなたが達成したいことの説明を私たちに提供する方が良いでしょう. SOのメンバーがアドバイスをくれると思います。

于 2008-09-23T12:58:33.513 に答える
0

パラメータとして Lambda 式を使用することをお勧めしますか? これにより、内部ジェネリック型を比較す​​る方法を指定できます。

于 2008-09-23T12:59:52.467 に答える
0

これについてコンパイルするときに警告は表示されませんが、== null 比較について話していると思いますか? はい、キャストはこれをすべてややきれいにするようです。

PS。比較子には別のクラスを使用する必要があります。2 つの役割 (ペアであることとペアを比較すること) を満たすこのクラスは、明らかに醜いです。

于 2008-09-23T13:01:39.090 に答える