0

一種の文字列ラッパー クラスを作成し、そのインスタンスを通常の文字列と交換可能な辞書キーとして使用したいと考えています。私はオーバーライドGetHashCodeしてEquals、奇妙に思える結果を得ました。問題を切り分けました。私のコードを見て、2 回目の検索で null が返される理由を説明してください。

void Main()
{
    var foo = new StringWrapper("foo");
    var h = new Hashtable {{ foo, "bar" }};
    Console.WriteLine(h["foo"]);
    Console.WriteLine(h[foo]); // null ??
}

public class StringWrapper
{
    readonly string wrapped;
    public StringWrapper(string s) {
        wrapped = s;
    }
    public override bool Equals(object obj) {
        return wrapped.Equals(obj);
    }
    public override int GetHashCode() {
        return wrapped.GetHashCode();
    }
    public override string ToString() {
        return wrapped;
    }
}
4

3 に答える 3

6

では、 ではなく、- になり、 aは、Equals(object obj)ではないものと等しいとは決して言わないことに注意してください。からラップされた文字列を抽出する必要があります。誰かがそれをハッシュテーブルに入れる以外の目的で使用する場合は、他のタイプでもある可能性があることを確認して考慮する必要があることに注意してください。objstringStringWrapperstringstringobjnullStringWrapperobj

于 2012-08-21T17:38:22.697 に答える
3

平等の実装は対称的でも反射的でもありません。

StringWrapper wrapper = new StringWrapper("foo");

Console.WriteLine(wrapper.Equals(wrapper)); // False
Console.WriteLine(wrapper.Equals("foo")); // True
Console.WriteLine("foo".Equals(wrapper)); // False

したがって、のドキュメントでObject.Equals指定されているルールに違反しています。(および他のクラス)は、これらのルールに違反しないHashtableことを期待しており、違反すると正しく機能しません。

ラッパーが元の値と等しいふりをしようとするラッパーではなく、カスタムコレクションが必要なようです。

(余談ですが、なぜまだジェネリックHashtableではなく非ジェネリックを使用しているのDictionary<,>ですか?)

于 2012-08-21T17:41:11.190 に答える
1

問題はあなたの Equals メソッドです:

public override bool Equals(object obj) {
    // wrapped is a String, but obj is (usually) a StringWrapper
    return wrapped.Equals(obj);
}

次のようなものが必要です。

public override bool Equals(object obj) {
    var other = obj as StringWrapper;
    return other != null && wrapped.Equals(other.wrapped);
}

編集:ジョンの答えによると、文字列と比較できるようにすることもできます:

public override bool Equals(object obj) {
    var other = obj as StringWrapper;
    return (other != null && wrapped.Equals(other.wrapped))
           || Object.Equals(wrapped, (obj as String));
}
于 2012-08-21T17:39:04.247 に答える