8

プログラムはこの実装で動作していました:

class Instrument
{
    public string ClassCode { get; set; }
    public string Ticker { get; set; }
    public override string ToString()
    {
        return " ClassCode: " + ClassCode + " Ticker: " + Ticker + '.';
    }
}

しかし、辞書でInstrumentを使用する必要があるため、equals/hashcodeを実装することにしました。

class Instrument
{
    public string ClassCode { get; set; }
    public string Ticker { get; set; }
    public override string ToString()
    {
        return " ClassCode: " + ClassCode + " Ticker: " + Ticker + '.';
    }

    public override bool Equals(object obj)
    {
        if (obj == null)
            return false;

        Instrument instrument = obj as Instrument;
        if (instrument == null)
            return false;

        return ((ClassCode.Equals(instrument.ClassCode)) && (Ticker.Equals(instrument.Ticker));
    }

    public override int GetHashCode()
    {
        int hash = 13;
        hash = (hash * 7) + ClassCode.GetHashCode();
        hash = (hash * 7) + Ticker.GetHashCode();
        return hash;
    }
}

これで、プログラムは動作を停止しました。そのような場所または同様の場所で、「KeyNotFoundException」を受け取ります。

if (cache.Keys.Any(instrument => instrument.Ticker == newTicker && instrument.ClassCode == newClassCode))

コードの一部がequalsを想定していて、ハッシュコードが実装されていない可能性はありますか?それとも私はそれらを間違って実装したのでしょうか?申し訳ありませんが、コードの最後の部分のようなC#の高度な機能に精通しておらず、equalsまたはhashCodeとどのように接続されているのかわかりません。

4

3 に答える 3

7

HashCodeメソッドとEqualsメソッドは、不変のプロパティのみに依存する必要があります。実装では、どちらもセッターを備えているため可変であるClassCodeとTickerを使用します。

于 2011-04-18T08:42:47.470 に答える
3

まず、を使用する代わりに、ContainsKeycache.Keys.Anyを使用できます。

bool contains = cache.ContainsKey(
    new Instrument { Ticker = newTicker, ClassCode = newClassCode });

1つ目はキーリスト全体(O(n))を反復処理し、2つ目はDictionaryに組み込まれているハッシュテーブル実装(O(1))を使用します。

次に、実装でnull参照を確認します。

public override bool Equals(object obj)
{
    if (obj == null)
        return false;

    Instrument instrument = obj as Instrument;
    if (instrument == null)
        return false;

    // 1. string.Equals can handle null references.
    // 2. object.ReferenceEquals for better preformances when it's the same object
    return (object.ReferenceEquals(this, instrument)) ||
        (string.Equals(ClassCode, instrument.ClassCode) &&
        string.Equals(Ticker, instrument.Ticker));
}

public override int GetHashCode()
{
    int hash = 13;
    if (ClassCode != null)
        hash = (hash * 7) + ClassCode.GetHashCode();
    if (Ticker!= null)
        hash = (hash * 7) + Ticker.GetHashCode();

    return hash;
}

それ以外は問題ありません。

于 2011-04-18T08:31:14.287 に答える
1

しかし、辞書でInstrumentを使用する必要があるため、equals/hashcodeを実装することにしました。

それは間違った理由です。あなたのクラスには、辞書での使用に適し、効率的で、テストされたEqualityとGetHashCodeの実装がすでにあります。

Equals()/ GetHashCode()を正しく実装しましたか?

いいえ。そもそもオーバーロードがありません==。そして、Instrumentを不変にした場合にのみ信頼できます。

最善の行動は、これらのメンバーを上書きしないことです。

このMSDNアドバイスも参照してください。「同等の保証」と

不変でない型で演算子==をオーバーライドすることはお勧めしません。

于 2011-04-18T10:11:44.367 に答える