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

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

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

Re[10]: string型の謎


(過去ログ 125 を表示中)

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

■74196 / inTopicNo.1)  string型の謎
  
□投稿者/ ぶなっぷ (15回)-(2014/12/08(Mon) 10:08:13)

分類:[.NET 全般] 

C++歴20年、C#歴半年の者です。
C#において、string型は参照型の扱いじゃないですか。
でも、以下のようにすると、
string Test = "aaa";
string Test2 = Test;
Test2 = "bbb";

Testの値は"aaa"のまま。
普通の参照型なら"bbb"に変わるはずで、変わらないと言うことは
operator=()がオーバーライドされているのか?

と思いきや、C#ではoperator=()はオーバーライド不可能ときたもんです。
もう、頭の中に???がいっぱいです(笑)。

引用返信 編集キー/
■74197 / inTopicNo.2)  Re[1]: string型の謎
□投稿者/ Hongliang (257回)-(2014/12/08(Mon) 10:27:06)
2014/12/08(Mon) 10:28:07 編集(投稿者)

ん?
Uri test = new Uri("http://example.com/test");
Uri test2 = test;
test2 = new Uri("http://example.com/test2");
testの値は"http://example.com/test"のままですよ?
引用返信 編集キー/
■74198 / inTopicNo.3)  Re[2]: string型の謎
□投稿者/ 774RR (190回)-(2014/12/08(Mon) 10:40:42)
const char* text1="aaa";
const char* text2=text1;
text2="bbb";
と同じだよね。あるいはもっと C# から直訳したっぽく書けば

std::wstring* text1=new std::wstring(L"aaa");
std::wstring* text2=text1;
text2=new std::wstring(L"bbb");
ってことになるわけだけど。

どこが疑問になるのかが疑問。

引用返信 編集キー/
■74199 / inTopicNo.4)  Re[3]: string型の謎
□投稿者/ ぶなっぷ (16回)-(2014/12/08(Mon) 11:18:37)
2014/12/08(Mon) 11:18:59 編集(投稿者)
どうやら私は何か大きな勘違いをしているようですね。
私が知りたいのは、以下のようなパターンとの違いです。

public class Temp
{
  public string Tmp;
};

Temp Test = new Temp();
Test.Tmp = "aaa";
var Test2 = Test;
Test2.Tmp = "bbb";

このケースでは Test.Tmpの値は"bbb"に変化します。

最初の例とこの例の違いが分からない男らしいです(^^;

引用返信 編集キー/
■74200 / inTopicNo.5)  Re[4]: string型の謎
□投稿者/ WebSurfer (412回)-(2014/12/08(Mon) 11:43:21)
No74199 (ぶなっぷ さん) に返信

最初の方は理解されたでしょうか?

> このケースでは Test.Tmpの値は"bbb"に変化します。

「このケース」では、Test と Test2 は同一の Temp オブジェクトのインスタンスを指して
いるから当然の結果では?
引用返信 編集キー/
■74202 / inTopicNo.6)  Re[4]: string型の謎
□投稿者/ shu (640回)-(2014/12/08(Mon) 11:50:58)
No74199 (ぶなっぷ さん) に返信

最初の例)
┌─┐         ┌────┐
│ a│───> │aaa     │
└─┘         └────┘
         ^ 
┌─┐      |
│ b│──────┘
└─┘
      ↓

┌─┐         ┌────┐
│ a│───> │aaa     │
└─┘         └────┘ 
        
┌─┐     ┌────┐
│ b│───> │bbb     │
└─┘     └────┘
ここを書き換え


後の例
┌─┐         ┌────┐          ┌────┐          ┌────┐
│ a│───> │        │───>  │Tmp     │───>  │aaa     │
└─┘         └────┘          └────┘          └────┘
         ^ 
┌─┐      |
│ b│──────┘
└─┘
      ↓

┌─┐         ┌────┐          ┌────┐         ┌────┐
│ a│───> │        │───>  │Tmp     │───> │bbb     │
└─┘         └────┘          └────┘         └────┘
         ^ 
┌─┐      |
│ b│──────┘
└─┘
                                    ここを書き換え


引用返信 編集キー/
■74203 / inTopicNo.7)  Re[5]: string型の謎
□投稿者/ 774RR (191回)-(2014/12/08(Mon) 12:05:46)
もうばっちり図解までされているので限りなく蛇足なわけだが C++ で書けば

struct Temp* Test1=new Temp;
struct Temp* Test2=Test1; // 同一のブツを指してる
Test1->Tmp を入れ替えれば Test2->Tmp も入れ替わってしかるべき

引用返信 編集キー/
■74204 / inTopicNo.8)  Re[4]: string型の謎
□投稿者/ WebSurfer (413回)-(2014/12/08(Mon) 12:08:27)
No74199 (ぶなっぷ さん) に返信

もう一つオマケに・・・

C# での文字列(String 型)の扱いについては、以下のページが参考になると思います。

文字列 (C# プログラミング ガイド)
http://msdn.microsoft.com/ja-jp/library/ms228362.aspx
引用返信 編集キー/
■74205 / inTopicNo.9)  Re[1]: string型の謎
□投稿者/ 魔界の仮面弁士 (189回)-(2014/12/08(Mon) 12:14:39)
No74196 (ぶなっぷ さん) に返信
> string Test = "aaa";
> string Test2 = Test;
> Test2 = "bbb";

// 変数 a と変数 b は、同一インスタンス(label1)を参照している
Label a = label1;
Label b = a;

// b の参照先を、別のインスタンス(label2)に変更する
b = label2;

※この場合、変数 a と 変数 b は別のラベルを参照しているため、
 a.Text と b.Text は連動しない。

-----------------------

No74199 (ぶなっぷ さん) に返信
> Temp Test = new Temp();
> Test.Tmp = "aaa";
> var Test2 = Test;
> Test2.Tmp = "bbb";

// 変数 x の参照先に "aaa" をセット
Label x = label3;
x.Text = "aaa";

// 変数 y にも、同じオブジェクトを参照させる
Label y = x;

// 変数 y の参照先に "bbb" をセット
y.Text = "bbb";

※この場合、変数 x と 変数 y は同一のラベル(label3)を参照しているため、
 x.Text と y.Text が連動する。
引用返信 編集キー/
■74206 / inTopicNo.10)  Re[5]: string型の謎
□投稿者/ ぶなっぷ (17回)-(2014/12/08(Mon) 12:38:18)
2014/12/08(Mon) 12:38:50 編集(投稿者)
なるほど、つまり
  Test2 = "bbb";
はTest2インスタンスの内部文字列を書き換えているわけではなく、
  "bbb"
という内部文字列を持った新たなstringインスタンスを生成し、
参照先をそのインスタンスに書き換えているというわけですな?

そういうことであれば納得です。

引用返信 編集キー/
■74209 / inTopicNo.11)  Re[6]: string型の謎
□投稿者/ WebSurfer (415回)-(2014/12/08(Mon) 12:46:54)
No74206 (ぶなっぷ さん) に返信

> Test2 = "bbb";
> はTest2インスタンスの内部文字列を書き換えているわけではなく、

そもそもそんなことはできません。紹介した MSDN ライブラリを読んでく
ださい。「文字列オブジェクトの不変性」のセクションあたり。せっかく
紹介しても、読んでもらえないのではがっかりです。
引用返信 編集キー/
■74210 / inTopicNo.12)  Re[6]: string型の謎
□投稿者/ 魔界の仮面弁士 (191回)-(2014/12/08(Mon) 13:07:37)
No74206 (ぶなっぷ さん) に返信
> なるほど、つまり
> Test2 = "bbb";
> はTest2インスタンスの内部文字列を書き換えているわけではなく、
> "bbb"
> という内部文字列を持った新たなstringインスタンスを生成し、
> 参照先をそのインスタンスに書き換えているというわけですな?

参照先の中身を直接書き換えたい場合は、このようなコードが必要になります。

class Program
{
 static void Main()
 {
  string Test = "C#";
  string Test2 = Test;
  Console.WriteLine("初期値は同じ:{0} / {1}", Test, Test2);
  // この段階では、「Object.ReferenceEquals(Test, Test2)」は true です。

  unsafe
  {
   fixed (char* p = Test)
   {
    p[0] = 'C';
    p[1] = '丼';
   }
   Console.WriteLine("両方変わる:{0} / {1}", Test, Test2);
  }
  // この段階でも、「Object.ReferenceEquals(Test, Test2)」は true です。
  // 通常は String 型は不変ですが、unsafe コードでの書き換えは可能です。


  Test = "VB";
  Console.WriteLine("片方だけ変わる:{0} / {1}", Test, Test2);
  // この段階では、Test 側が別のインスタンスになるため、
  // 「Object.ReferenceEquals(Test, Test2)」は false です。


  Console.ReadKey();
 }
}
引用返信 編集キー/
■74211 / inTopicNo.13)  Re[7]: string型の謎
□投稿者/ 774RR (192回)-(2014/12/08(Mon) 13:09:29)
> という内部文字列を持った新たなstringインスタンスを生成し、
> 参照先をそのインスタンスに書き換えているというわけですな?

はい、その理解で大丈夫。

「文字列オブジェクトの不変性」により System.String に対する操作の結果は全て
new System.String された新たな System.String オブジェクト(インスタンス)に返却されるわけ。
(C++ ならば、常に演算の際に new std::wstring された結果が得られると考えると良い)
提示解説の //Output: Hello のところなど特に注意。

C の char[] に sprintf/strcat しているのと同等のつもりで
System.String の演算を(特に連結操作)繰り返すと性能が出ないっす。
System.Text.StringBuilder をうまく使う必要があるわけっす。

C++ プログラマのための C# 入門、みたいな記事を書くなら
C# の参照型は C++ でいうところのポインタ型に相当していて
C# ソースコード上の記述はあたかも「値」を扱っているように見えるが実際にはポインタ経由の操作。
ブツ (インスタンス・オブジェクト)は new したものしか存在しない。
ってことで。

引用返信 編集キー/
■74212 / inTopicNo.14)  Re[7]: string型の謎
□投稿者/ 774RR (193回)-(2014/12/08(Mon) 14:21:08)
<offtopic>

No74209 WebSurfer 氏
> 読んでもらえないのではがっかりです

おいらは No74206 の発言を素朴に

リンク先の解説記事を読む前は
> Test2インスタンスの内部文字列を書き換えている
と思っていたけど、リンク先の解説記事を読んで
> わけではなく、
ということを理解した、つまり、ちゃんと読んでくれてるんだな、って解釈したけど。

なぜ「読んでもらえない」と解釈したのか、その辺の解説を希望してみるとかしないとか。
# 最近 WebSurfer 氏の発言はどうも過激に走っている気のせいがする。
# いや、おいら過激なのは嫌いじゃないですけど。でもでも、
# 質問して最初についたレスがやたらけんか腰だったりすると、質問側としてはきっと悲しい気持ちがするっす。
# 全部教えてクン(仕事の依頼クン)でない場合はもっと穏健に対応してほしいような気のせいがします。

引用返信 編集キー/
■74213 / inTopicNo.15)  Re[8]: string型の謎
□投稿者/ ぶなっぷ (18回)-(2014/12/08(Mon) 14:40:53)
みなさん、ありがとうございます。

> ブツ (インスタンス・オブジェクト)は new したものしか存在しない。
これが核心を突いていますね。
stringが参照型である以上、それが文字列リテラルであろうとnewしたものをぶち
込むしかないぞと。

よく理解できました。

解決済み
引用返信 編集キー/
■74216 / inTopicNo.16)  Re[8]: string型の謎
□投稿者/ WebSurfer (417回)-(2014/12/08(Mon) 17:29:27)
No74212 (774RR さん) に返信

> なぜ「読んでもらえない」と解釈したのか、その辺の解説を希望してみるとかしないとか。

その時は今までの経験からの感ベースでそう思ったのでそう書きました(個人的には感は
よく当たると思ってます)。今も、直近のレスを見ると、やっぱり読んでいただいてない
と、ほぼ確信レベルで、思ってます。
解決済み
引用返信 編集キー/
■74219 / inTopicNo.17)  Re[9]: string型の謎
□投稿者/ わるいけど (1回)-(2014/12/09(Tue) 01:58:49)

> その時は今までの経験からの感ベースでそう思ったのでそう書きました(個人的には感は
> よく当たると思ってます)。今も、直近のレスを見ると、やっぱり読んでいただいてない
> と、ほぼ確信レベルで、思ってます。

あんたの勘や思い込みは外れまくってるのを散々見てる。
あんた思い込みで人を侮辱したりするの平気なくせに、
自分が何か言われたらそれは質問者に確認したのかとかよく言ってるよね?
どんなダブルスタンダードだ。

あんたに思うことは一つ。
ただ身勝手なだけ、人に言うのは平気なくせに自分ははるかにましなことでも言われたら許せない。
身勝手な人だ。

引用返信 編集キー/
■74241 / inTopicNo.18)  Re[10]: string型の謎
□投稿者/ Oracular (1回)-(2014/12/09(Tue) 23:26:08)
No74219 (わるいけど さん) に返信
>
>>その時は今までの経験からの感ベースでそう思ったのでそう書きました(個人的には感は
>>よく当たると思ってます)。今も、直近のレスを見ると、やっぱり読んでいただいてない
>>と、ほぼ確信レベルで、思ってます。
>
> あんたの勘や思い込みは外れまくってるのを散々見てる。
> あんた思い込みで人を侮辱したりするの平気なくせに、
> 自分が何か言われたらそれは質問者に確認したのかとかよく言ってるよね?
> どんなダブルスタンダードだ。
>
> あんたに思うことは一つ。
> ただ身勝手なだけ、人に言うのは平気なくせに自分ははるかにましなことでも言われたら許せない。
> 身勝手な人だ。
>

匿名性を利用して煽りくれるのも相当身勝手ではある。

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


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

このトピックに書きこむ

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

管理者用

- Child Tree -