2

基本的にここでは、文字列が不変であることを例で示したいので、以下の例を取り上げました。GetHashCode() がアドレスを返さないことはわかっていますが、両方の変数が異なるメモリ位置を参照していることをどのように区別できますか?

以下のコードでは、文字列変数のアドレスが必要です

        string s = "hello";
        Console.WriteLine(s.GetHashCode());
        s = s + "User";
        Console.WriteLine(s.GetHashCode());

ただし、String Builder の場合、GetHashCode() は同じ値を返します

        StringBuilder sb = new StringBuilder();
        sb.Append("hi");
        Console.WriteLine(sb.GetHashCode());
        sb.Append("hello");
        Console.WriteLine(sb.GetHashCode());
4

3 に答える 3

8

2 つの異なる変数を使用するだけで、object.ReferenceEquals代わりに次のようになります。

string x = "hello";
string y = x + "User";
Console.WriteLine(ReferenceEquals(x, y));

確かに印刷するだけxy、その時点でそれらが異なることが示されます...わずかな代替手段として:

string s = "hello";
string original = s;
Console.WriteLine(ReferenceEquals(s, original)); // True
s = s + "User";
Console.WriteLine(ReferenceEquals(s, original)); // False

おそらくそれはあなたが探していたものに近いですか?

于 2013-07-03T17:56:03.413 に答える
7

与えられた例では、実際にアドレスを知る必要はありません.2つのオブジェクトのアドレスが同じかどうかだけを知りたいのです。

string s1 = "hi";
string s2 = s1;
Console.WriteLine(object.ReferenceEquals(s1, s2)); // True
s2 = s2 + " world";
Console.WriteLine(object.ReferenceEquals(s1, s2)); // False

補足説明:object==演算子はデフォルトで を使用しますが、C# では演算子がオーバーライドされるobject.ReferenceEquals()ため、2 つの文字列が等しいかどうかは文字列が等しいかどうかに基づいてチェックされます。さらに複雑なことに、コンパイラは、コンパイル時に正確に等しいと判断できる定数文字列を「インターン」します。これらの動作の組み合わせにより、非常に奇妙な動作が発生します。string==

string s1 = "john";
object s2 = "john";
string s3 = new StringBuilder(s1).ToString();
Console.WriteLine(s1 == s2); // True
Console.WriteLine(s2 == s1); // True
Console.WriteLine(s1 == s3); // True
Console.WriteLine(s3 == s1); // True
Console.WriteLine(s2 == s3); // False
Console.WriteLine(s3 == s2); // False
于 2013-07-03T17:55:44.730 に答える
0

Object.ReferenceEquals(a, b)falseiffaを返しb、異なるオブジェクト (したがって異なるアドレス) への参照です。

文字列ビルダのハッシュ コードは、おそらく文字列ビルダが格納する文字列値からではなく、文字列ビルダのアドレスから構築されます。

s + "hello"一方、 は、 とは異なるハッシュ コードを持つ新しいオブジェクトを作成しますs

于 2013-07-03T17:56:33.090 に答える