C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[8]: object 同士の比較


(過去ログ 28 を表示中)

[トピック内 16 記事 (1 - 16 表示)]  << 0 >>

■13104 / inTopicNo.1)  object 同士の比較
  
□投稿者/ OGAKUZU (13回)-(2008/01/24(Thu) 13:31:44)

分類:[C#] 

環境:VS 2005 Standard

object n1 = 123;
object n2 = 123;

n1 == n2 .... 式1
(int)n1 == (int)n2 .... 式2

上記において、式1は false、式2は true になります。

式1と式2で結果が異なる理由がわかりません。
(どちらも true になると期待したのですが)

よろしくお願いします。

引用返信 編集キー/
■13106 / inTopicNo.2)  Re[1]: object 同士の比較
□投稿者/ もみじ (1回)-(2008/01/24(Thu) 13:38:09)
こんにちは(^^

> n1 == n2
これは参照の比較
それぞれ、参照先は違うので False

> (int)n1 == (int)n2
これは値の比較

となるので違うのだと思います。

間違ってたらすみません。。



引用返信 編集キー/
■13109 / inTopicNo.3)  Re[2]: object 同士の比較
□投稿者/ 七曜 (46回)-(2008/01/24(Thu) 14:57:03)
値型(intとかlongとかね)の比較の==は、値が等しければtrueを返しますが
Objectの様な参照型の比較の==は、同じオブジェクトの場合はtrueを返しますが、それ以外は(型は一緒でもインスタンスが異なるので)falseになります。
ここら辺は、MSDNの

[== 演算子 (C# リファレンス)]
http://msdn2.microsoft.com/ja-jp/library/53k8ybth(VS.80).aspx

に書いてありますので、ご一読ください。


また、クラスによっては==で比較した際の振る舞いを変えている(あるいは変えた方が意味的に通じやすい)場合もあるので

[Equals() と演算子 == のオーバーロードに関するガイドライン (C# プログラミング ガイド)]
http://msdn2.microsoft.com/ja-jp/library/ms173147(VS.80).aspx

なんかも見ておくと良いでしょう。

引用返信 編集キー/
■13111 / inTopicNo.4)  Re[1]: object 同士の比較
□投稿者/ OGAKUZU (14回)-(2008/01/24(Thu) 16:36:00)
もみじさん、七曜さん、ご指導ありがとうございました。
おおよそ理解できました。

> object n1 = 123;
> object n2 = 123;

において

n1 == n2 は、n1, n2 が指す場所の比較
(int)n1 == (int)n2 は、n1, n2 が指す場所の中身の比較
だったのですね。

ちなみに

object s1 = "ABC";
object s2 = "ABC";

において

s1 == s2 は True になりますが、これは s1 と s2 の参照が等価
(s1, s2 が指す場所が同じ)であるためと理解しました。

メモリ空間を節約する機構が働き、同じ場所を共有したのですね。
↑文献が見当たらなかったので勝手に解釈してしまいました。

お世話になりました。

解決済み
引用返信 編集キー/
■13131 / inTopicNo.5)  Re[2]: object 同士の比較
□投稿者/ 渋木宏明(ひどり) (637回)-(2008/01/24(Thu) 22:57:56)
渋木宏明(ひどり) さんの Web サイト
> おおよそ理解できました。

string 型は特殊な振る舞いをするように実装されているので、ボクシングと一緒くたにすると変な誤解をしてしまうかも。

例えば

string s1 = "abc";
string s2 = "ABC".ToLower();

の時

object n1 = s1;
object n2 = s2;

System.Console.WriteLine(n1 == n2);
System.Console.WriteLine(s1 == s2);

の結果を正しく予測できます?





>
> ちなみに
>
> object s1 = "ABC";
> object s2 = "ABC";
>
> において
>
> s1 == s2 は True になりますが、これは s1 と s2 の参照が等価
> (s1, s2 が指す場所が同じ)であるためと理解しました。
>
> メモリ空間を節約する機構が働き、同じ場所を共有したのですね。
> ↑文献が見当たらなかったので勝手に解釈してしまいました。
>
> お世話になりました。
>
引用返信 編集キー/
■13132 / inTopicNo.6)  Re[3]: object 同士の比較
□投稿者/ 七曜 (48回)-(2008/01/24(Thu) 23:11:41)
No13131 (渋木宏明(ひどり) さん) に返信
>>おおよそ理解できました。
>
> string 型は特殊な振る舞いをするように実装されているので、ボクシングと一緒くたにすると変な誤解をしてしまうかも。

そうですね。
.NET Frameworkの型に関する知識は正しく覚えておく事は重要の割には知らない人が多いので・・・
MSDNの型に関するトピックを読んでおくと良いでしょう。

[型 (C# リファレンス)]
http://msdn2.microsoft.com/ja-jp/library/3ewxz6et(VS.80).aspx

ボクシング/アンボクシング(ボクシング化とボクシング化解除)も併せて、理解しておくと良いですね。
(上記ページからリンクでたどれます。)


引用返信 編集キー/
■13164 / inTopicNo.7)  Re[1]: object 同士の比較
□投稿者/ OGAKUZU (15回)-(2008/01/25(Fri) 11:17:15)
> string s1 = "abc";
> string s2 = "ABC".ToLower();
>
> の時
>
> object n1 = s1;
> object n2 = s2;
>
> System.Console.WriteLine(n1 == n2);
> System.Console.WriteLine(s1 == s2);
>
> の結果を正しく予測できます?

↑このコメントをいただいた時点では、結果を予測することができませんでした。
(動作パターンがいくつも想定され、ひとつの答えにたどり着きませんでした)

なので、実際に動かしてみて、また

> [型 (C# リファレンス)]
> http://msdn2.microsoft.com/ja-jp/library/3ewxz6et(VS.80).aspx
>
> ボクシング/アンボクシング(ボクシング化とボクシング化解除)も併せて、理解しておくと良いですね。
> (上記ページからリンクでたどれます。)

↑この資料に目を通した上で、自分なりに、動作を解釈しました。

◆実行内容と結果

  // ひどりさんからの宿題

string s1 = "abc";
string s2 = "ABC".ToLower();
object n1 = s1;
object n2 = s2;
System.Console.WriteLine(n1 == n2); // 結果:False
System.Console.WriteLine(s1 == s2); // 結果:True

  // 自分で追加

string s3 = "abc";
object n3 = s3;
System.Console.WriteLine(n1 == n3); // 結果:True
System.Console.WriteLine(s1 == s3); // 結果:True

System.Console.WriteLine(object.ReferenceEquals(n1, n2)); // 結果:False
System.Console.WriteLine(object.ReferenceEquals(s1, s2)); // 結果:False
System.Console.WriteLine(object.ReferenceEquals(n1, n3)); // 結果:True
System.Console.WriteLine(object.ReferenceEquals(s1, s3)); // 結果:True

◆解釈

> string s1 = "abc";
> string s2 = "ABC".ToLower();
> string s3 = "abc";

s1, s3 は、値が同じなので「メモリ空間を節約する機構が働き」実データを共有した。

s1, s2 は、値は同じ(どちらも"abc")であるが、.ToLower()が絡んだので、異なる実データを持った。
(string クラスにもいろいろ事情があるのだと思います)

> object n1 = s1;
> object n2 = s2;
> object n3 = s3;

n1, n3 は、共有されている実データからのボクシング化なので、ヒープ上のデータも共有した。
n1, n2 は、異なる実データからのボクシング化なので、ヒープ上のデータも別々に確保した。

以上です。

渋木宏明(ひどり)さん、七曜さん、ありがとうございました。

つっこみどころがありましたら、引き続きご指導お願いします。

引用返信 編集キー/
■13167 / inTopicNo.8)  Re[2]: object 同士の比較
□投稿者/ 囚人 (282回)-(2008/01/25(Fri) 11:39:35)
文字列に関しては、その手の「参照が同じかどうか」は、いつでも同じ解を得られるとは考えない方が良いです。
http://blogs.wankuma.com/shuujin/archive/2007/10/11/101557.aspx

リテラル文字なのか、アセンブリにある属性を付与したか、ネイティブイメージ化したのか、CLR のバージョンは何かなど、いろいろな事を全て考えて、初めて一致した解を得られます。
引用返信 編集キー/
■13188 / inTopicNo.9)  Re[3]: object 同士の比較
□投稿者/ OGAKUZU (16回)-(2008/01/25(Fri) 15:35:52)
> http://blogs.wankuma.com/shuujin/archive/2007/10/11/101557.aspx

記事をありがとうございました。
まだ全ては理解できておりませんが、たしかに難しいテーマのようですね。

渋木宏明(ひどり)さんからの宿題も、将来は違う結果が出る(True/False が逆になる)
かもしれませんね。

囚人さん、ご指導ありがとうございました。

引用返信 編集キー/
■13297 / inTopicNo.10)  Re[2]: object 同士の比較
□投稿者/ 渋木宏明(ひどり) (639回)-(2008/01/26(Sat) 19:45:01)
渋木宏明(ひどり) さんの Web サイト
> s1, s3 は、値が同じなので「メモリ空間を節約する機構が働き」実データを共有した。

は「いつ」起きているでしょう?

コンパイル時? それとも実行時?

> s1, s2 は、値は同じ(どちらも"abc")であるが、.ToLower()が絡んだので、異なる実データを持った。
> (string クラスにもいろいろ事情があるのだと思います)

string 型は、「s1, 2 の実体が異なるとしても、値が同じなら s1 == s2 が成立する方が自然に見える」ので、そういう振る舞いをするように実装されています。

これは、単純に自分でクラスを定義した場合の挙動とは異なります。


>>object n1 = s1;
>>object n2 = s2;
>>object n3 = s3;
>
> n1, n3 は、共有されている実データからのボクシング化なので、ヒープ上のデータも共有した。
> n1, n2 は、異なる実データからのボクシング化なので、ヒープ上のデータも別々に確保した。

間違ってます。

string 型は値型ではなく、参照型なので boxing は発生しません。

引用返信 編集キー/
■13361 / inTopicNo.11)  Re[3]: object 同士の比較
□投稿者/ OGAKUZU (17回)-(2008/01/28(Mon) 17:58:04)
>>s1, s3 は、値が同じなので「メモリ空間を節約する機構が働き」実データを共有した。
>
> は「いつ」起きているでしょう?
> コンパイル時? それとも実行時?

内部で String.Intern メソッドが使われている気がするので、答えは「実行時」です。
たぶん。

>>s1, s2 は、値は同じ(どちらも"abc")であるが、.ToLower()が絡んだので、異なる実データを持った。
>>(string クラスにもいろいろ事情があるのだと思います)
>
> string 型は、「s1, 2 の実体が異なるとしても、値が同じなら s1 == s2 が成立する方が自然に見える」ので、そういう振る舞いをするように実装されています。

そうですね。
資料を見直したところ、ここへ載っていました。
http://msdn2.microsoft.com/ja-jp/library/53k8ybth(VS.80).aspx
引用「string 型の場合は、== は文字列の値を比較します。」

> >>object n1 = s1;
> >>object n2 = s2;
> >>object n3 = s3;
>>
>>n1, n3 は、共有されている実データからのボクシング化なので、ヒープ上のデータも共有した。
>>n1, n2 は、異なる実データからのボクシング化なので、ヒープ上のデータも別々に確保した。
>
> 間違ってます。
>
> string 型は値型ではなく、参照型なので boxing は発生しません。

確認したところ、おっしゃるとおり boxing は発生せず、s1 のインスタンスが
そのまま n1 に適用されていますね。

確認結果

string s1 = "abc";
object n1 = s1;
System.Console.WriteLine(object.ReferenceEquals(n1, s1)); // 結果:True

渋木宏明(ひどり)さん、ご指導ありがとうございました。

引用返信 編集キー/
■13363 / inTopicNo.12)  Re[4]: object 同士の比較
□投稿者/ 渋木宏明(ひどり) (644回)-(2008/01/28(Mon) 18:35:52)
渋木宏明(ひどり) さんの Web サイト
> >>s1, s3 は、値が同じなので「メモリ空間を節約する機構が働き」実データを共有した。
>>
>>は「いつ」起きているでしょう?
>>コンパイル時? それとも実行時?
>
> 内部で String.Intern メソッドが使われている気がするので、答えは「実行時」です。
> たぶん。

NOです。文字列リテラルの「おまとめ」はコンパイル時に行われます。

実際に「おまとめ」を行うかどうかもコンパイラ任せです。

実行時だとかなり効率が悪くなるし、実行時に「おまとめ」が行われのであれば

string s1 = "abc";
string s2 = "ABC".ToLower();

を「おまとめ」しないのはつじつまがあわなくないですか?

そしてこの「おまとめ」が行われるのも所詮は1つのコンパイル単位の中が限界です。

仮に "abc" という文字列が a.dll, b.dll に含まれていたとしても、これらの実体はまったく別のものです。

引用返信 編集キー/
■13395 / inTopicNo.13)  Re[5]: object 同士の比較
□投稿者/ OGAKUZU (18回)-(2008/01/29(Tue) 10:07:55)
> NOです。文字列リテラルの「おまとめ」はコンパイル時に行われます。
>
> 実際に「おまとめ」を行うかどうかもコンパイラ任せです。
>
> 実行時だとかなり効率が悪くなるし、実行時に「おまとめ」が行われのであれば
>
> string s1 = "abc";
> string s2 = "ABC".ToLower();
>
> を「おまとめ」しないのはつじつまがあわなくないですか?

たしかに、コンパイル時に行われると考えれば、つじつまは合いますね。
コンパイラは、.ToLower()が"ABC"を"abc"に変換することを知らないわけですから。

> そしてこの「おまとめ」が行われるのも所詮は1つのコンパイル単位の中が限界です。
>
> 仮に "abc" という文字列が a.dll, b.dll に含まれていたとしても、これらの実体はまったく別のものです。

.dll についてはまだ作成能力がないため確認できていませんが、異なる Form 間では「おまとめ」が行われる
ことを確認しました。

渋木宏明(ひどり)さん、お手数をおかけしました。
ありがとうございました。

引用返信 編集キー/
■13403 / inTopicNo.14)  Re[6]: object 同士の比較
□投稿者/ なちゃ (101回)-(2008/01/29(Tue) 11:35:49)
インターン化はJITコンパイル時くらいだったと思いますよ。
まあそれとは別にコンパイル単位でもまとめられてる気はしますが、自信なし

なのでアセンブリが違っても同じインスタンスになると思います。
まあこれは別に保証された動作みたいなものではないですが。

引用返信 編集キー/
■13487 / inTopicNo.15)  Re[7]: object 同士の比較
□投稿者/ OGAKUZU (19回)-(2008/01/30(Wed) 08:35:07)
なちゃさん、ありがとうございます。

> インターン化はJITコンパイル時くらいだったと思いますよ。
> まあそれとは別にコンパイル単位でもまとめられてる気はしますが、自信なし

ここまで深いレベルですと、私が調べられる範疇を超えている気がします。

> まあこれは別に保証された動作みたいなものではないですが。

通常は、システムまかせにして、プログラマが気を使うところではないようですね。

どうもお世話になりました。

引用返信 編集キー/
■13548 / inTopicNo.16)  Re[8]: object 同士の比較
□投稿者/ OGAKUZU (20回)-(2008/01/31(Thu) 08:47:56)
一応「解決済み」にさせていただきます。
みなさん、ありがとうございました。

解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -