2

ConcurrentDictionaryこのデータキーが以前に追加されたかどうかを確認するために使用したいのですが、以前に追加したキーをまだ追加できるようです。

コード:

    public class pKeys
    {
        public pKeys()
        { }
        public pKeys(long sID, long pID)
        {
            this.seID = sID;
            this.pgID = pID;

        }
        public long seID;
        public long pgID;
    }

    public static ConcurrentDictionary<pKeys, bool> existenceDic 
= new ConcurrentDictionary<pKeys, bool>();

テストコード:

    pKeys temKey = new pKeys(111, 222);
    bool res = existenceDic.TryAdd(temKey, true);
    Console.WriteLine(res);

    temKey = new pKeys(111, 222);
    res = existenceDic.TryAdd(temKey, true);
    Console.WriteLine(res);

結果:

true
true
4

1 に答える 1

3

GetHashCode()と をオーバーライドしていないため、同じ値を含む 2 つの異なるインスタンスを追加できますEquals()。これにより、デフォルトの等値比較が使用されます。参照型の場合、参照自体を単純に比較します。この場合、2 つの異なるインスタンスは常に異なる値と見なされます。

1 つのオプションは、型をstructではなく a にすることですclass。これは、フィールド値を考慮したデフォルトの比較を使用します。

GetHashCode()または、先に進んでとをオーバーライドすることもできますEquals()。例えば:

public class pKeys
{
    public pKeys()
    { }
    public pKeys(long sID, long pID)
    {
        this.seID = sID;
        this.pgID = pID;

    }
    public readonly long seID;
    public readonly long pgID;

    public override int GetHashCode()
    {
        return seID.GetHashCode() * 37 + pgID.GetHashCode();
    }

    public override bool Equals(object other)
    {
        pKeys otherKeys = other as pKeys;

        return otherKeys != null &&
            this.seID == otherKeys.seID &&
            this.pgID == otherKeys.pgID;
    }
}

ノート:

  • ハッシュコードは、個々の値のハッシュコードに基づいて計算されます。1 に 37 を掛けると、これは単純に便利な素数です。より良い「混合」のために、はるかに大きな素数を使用することを好む人もいます。ほとんどのシナリオでは、上記は問題なく機能します。
  • 提案された解決策、値を文字列に変換し、それらを連結し、そのハッシュコードを返すことには、いくつかのマイナス面があることに注意してください。
    • ハッシュ コードを生成するためだけに、3 つの文字列インスタンスを作成する必要があります。メモリのオーバーヘッドだけでも十分に悪いですが、もちろん 2 つの整数をフォーマットするコストもあります。
    • 文字列からハッシュ コードを生成すると、整数値から生成するよりも計算コストが高くなります。
    • 異なる値が同じ文字列になりやすいため、衝突のリスクがはるかに高くなります ((11, 2222) と (111, 222) など)。
  • readonly私はあなたのフィールドに追加しました。これは、型を a にすることに決めた場合 (つまり、メソッドをオーバーライドしない場合でも)重要です。structしかし、クラスの場合でも、同等である可変型は大きな問題です。ハッシュベースのコレクションに追加された後に変更されると、コレクションが事実上破損するためです。ここで使用readonlyすると、型が不変になります。(また、私見 public フィールドは避けるべきですが、それらが必要なreadonly場合は、等値メソッドをオーバーライドしなくても、それらは間違いなくあるべきです)。
  • メソッド内で正確な型の等価性をチェックすることを好む人もいEquals()ます。実際、これは良いアイデアであることが多く、オブジェクトが比較されるシナリオが単純化され、コードがより保守しやすくなります。ただし、例として、代入可能性 (つまりas) の方が読みやすく、とにかく多くのシナリオで有効です。

追加のガイダンスについては、 object.GetHashCode() を適切にオーバーライドする方法に関する一般的なアドバイスとガイドラインを参照してください。

于 2015-01-17T03:49:18.053 に答える