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

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

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

stringって本当に参照型?


(過去ログ 4 を表示中)

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

■3817 / inTopicNo.1)  stringって本当に参照型?
  
□投稿者/ haiji 二等兵(1回)-(2006/05/23(Tue) 18:16:42)

分類:[C#] 


分類:[C#] 

はじめまして。C++からC#に移行中のものです。
ずっと悩んでいるんですが、stringは参照型といいながら、実際の動作は値型のようなきがしてなりません。



[例1]

string a = "1";
string b = a;
string c = b;

Console.WriteLine( "a=" + a + " b=" + b + " c=" + c );

b = "2";

Console.WriteLine( "a=" + a + " b=" + b + " c=" + c );


結果は
a=1 b=1 c=1
a=1 b=2 c=1


参照型なら
a=1 b=1 c=1
a=2 b=2 c=2
となるのが正しいような気がするんですが・・・・・・



[例2]



string a = "1";
Console.WriteLine( "a=" + a );
Sub( a );
Console.WriteLine( "a=" + a );



static void Sub( string b )
{
b = "2";
}



関数の引数としてstringを与えて、関数内で内容を書き換えても影響されず、結果は
a=1
a=1
となってしまいますが、参照型なら
a=1
a=2
となるような・・・・




以上の例は、C#の「クラス」と「構造体」で似たような実験をしたときは、それぞれ参照型、値型として、私の期待どおりになってくれます。





調べてみるとstring型にはいろいろ特殊事情があるようで、
「stringクラスは不変の文字列である為、文字列を変更する度に実際には新しい文字列オブジェクトが生成される」
というのを見つけました。上記実験の結果は、1によるもの??
ちなみにstringでは「operator==はオーバーロードして値が同じときtrueを返すようになっている。」ということで
if ( a== b ) ....が、期待どおりに動くようになっています。

要するにstringは、
代入したり関数の引数に与えると自動的にあたらしいインスタンスが形成され、比較するときは自動的にインスタンス同士を比較してくれる、
型ってことになりますよね。これって、とどのつまり値型の動作そのものに思えてきます。


どこかまちがって理解しているとすると、それはどこなのでしょうか?だれか助けてください。

0
引用返信 編集キー/
■3830 / inTopicNo.2)  Re[1]: stringって本当に参照型?
□投稿者/ 囚人 二等兵(9回)-(2006/05/24(Wed) 00:55:47)

分類:[C#] 

>stringは参照型といいながら、実際の動作は値型のようなきがしてなりません。

この言葉は的を射てますね。
その通りです。値型のような動きをする参照型です。

string a = "1";
string b = a;
string c = b;

a,b,c 自体には、"1への参照が入っています。なので「文字列変数」は参照型です。

b = "2";

b には"2"の参照が入ります。b に "2"の参照が入っただけなので、a,c の参照は当然変化しませんよね?

つまり、「文字列の代入」という行為は、「文字列変数の値(中身)」を書き換えているのではなく、参照を再設定しているということです。

string a = new string("1");
string b = a;
string b = new string("2");

こんな感じの動きです。ここで a が "2" になるかと言ったら…なりませんよね。

0
引用返信 編集キー/
■3831 / inTopicNo.3)  Re[2]: stringって本当に参照型?
□投稿者/ 中博俊 神(446回)-(2006/05/24(Wed) 01:11:11)
中博俊 さんの Web サイト

分類:[C#] 

文字列だけは特殊も特殊。
で、それだけの特殊コーディングをして、参照型だけれども値型的な使い方が出来なきゃ価値が無いという判断でしょう。
VB的ともいえるかもしれませんが。

#それよりC++からC#にのりかえなくてもC++/CLIがあるじゃないか!! (あっ本が出るんでそれの宣伝です(^^;)

0
引用返信 編集キー/
■3842 / inTopicNo.4)  Re[3]: stringって本当に参照型?
□投稿者/ haiji 二等兵(2回)-(2006/05/24(Wed) 11:00:51)

分類:[C#] 

みなさまありがとうございます。

>その通りです。値型のような動きをする参照型です。

>文字列だけは特殊も特殊。

はっきり言っていただいてすっきりしました。
stringの機能としてはこの動作が使いやすいのはたしかなんですが、C#の入門書やWebの解説はどこも「stringは参照型」とさらっと流しているだけなので、なんでやねん・・・って苦しんでました。


>#それよりC++からC#にのりかえなくてもC++/CLIがあるじゃないか!!

さすがにVC6が使いづらくなってきたところにExpress Editionがタダでくばられたので、本当ならVC++2005Express Editionにいく予定だったんです。
でもどうしても昔のVC6のソースがコンパイルできなくて、あきらめてしまいました。
最近、corewin_express.vspropsを書き換えないと、ウインドウベースのソフトを作成できないことをやっと知りましたが、ときすでにおそく、C#のほうへと流れてしまいました。もっとはやくその本を手にしていればヨカッタです。

VC#は、C++Builderも使い込んでいた身としては、
C# = C++ + STL
.NET = VCL
が、あまりにそっくりで、おそろしいほどすんなり移行できました。VC#ってDelphi作ったヒトがBorlandから引っこ抜かれて作ったんでしたっけ。
今の悩みはスピードです。先日、VC6+DirectXでつくったゲームを、C#+ManagedDirectXで作り直してみたんですが、きっちり2割遅くなってました。
CLIでないnative C#みたいのがでないかな〜




0
引用返信 編集キー/
■3845 / inTopicNo.5)  Re[4]: stringって本当に参照型?
□投稿者/ 中博俊 神(448回)-(2006/05/24(Wed) 11:34:34)
中博俊 さんの Web サイト

分類:[C#] 

>今の悩みはスピードです。先日、VC6+DirectXでつくったゲームを、C#+ManagedDirectXで作り直してみたんですが、きっちり2割遅くなってました。

きっちりプロファイルしてくださいね。
2割の遅さがどこに由来しているかを把握しておかないと。

おそらくネイティブとのInteropだけでは語れないところがあると思います。
#あと2割って半年くらいのベースアップで解決できるじゃんとかっていうおもいもありますが。(^^;;


0
引用返信 編集キー/
■3847 / inTopicNo.6)  Re[3]: stringって本当に参照型?
□投稿者/ 青柳 臣一 二等兵(1回)-(2006/05/24(Wed) 11:38:38)
青柳 臣一 さんの Web サイト

分類:[C#] 

文字列定数、たとえば、"1" なども System.String クラスのインスタンスである、という点は特殊と言えば特殊ですね。なので、囚人さんが書かれたように
string a = "1";

string a = new string("1");
と同じ意味になるわけです。
ちなみに、"abc".Substring(...) とか "abc".Length とかもちゃんとコンパイルできます(C# の場合)。

しかし、System.String 自体はごく普通の参照型です。どこにも特殊なことはないと思います。
> 以上の例は、C#の「クラス」と「構造体」で似たような実験をしたとき
> は、それぞれ参照型、値型として、私の期待どおりになってくれます。
それは、上記の 「文字列定数も String のインスタンス」 という点を考慮せず
string b.InnerData = "2";
のように b の内容を変更していると捕らえていたからだと思います。

> 「stringクラスは不変の文字列である為、文字列を変更する度に実際
> には新しい文字列オブジェクトが生成される」

これも特殊事情というものではなく、単に 「そういう仕様で String クラスを作った」 というだけです。String クラスには中の文字列を変更するメソッド/プロパティはありません(というか、無いように作った)。たとえば Trim() メソッドは先頭と末尾の空白を削除した文字列を返すメソッドであって、中身の文字列を変更したりはしないわけです。これのおかげで
string a = "abc ";
string b = a;
string c = a.Trim();
とした場合に a、b は "abc " で c は "abc" となるわけです。もし Trim() メソッドが不変性を崩すような実装(中身を変更する)になっていて a も "abc" に変化してしまうと、b は a と同じインスタンスを参照しているのですから、b も "abc" になってしまいます。これはこれで 「そういう仕様」 とするのもアリだとは思いますが、文字列クラスとしては使いにくくなるだろうということで 「不変」 になるようにしただけです。
で、「不変」 と言っても、コンストラクタの引数のみで内容をセットできて、それ以外では一切内容の変更ができないようにしておく、というだけでぜんぜん特殊なことはやってないわけです。

0
引用返信 編集キー/
■3852 / inTopicNo.7)  Re[5]: stringって本当に参照型?
□投稿者/ haiji 二等兵(5回)-(2006/05/24(Wed) 13:05:52)

分類:[C#] 

いろいろ深いですね。
解決マークをつけさせていただきます。ありがとうございました。

以下、余談ですが、

値型と参照型の分類は内部の変数の管理方法の違いからくるのが定義なんでしょうが、プログラムする側からとらえると、はじめの[例1][例2]のような使用法上の違い(と効率)に注意を払って使用するのが実際だと思います。ところが、stringは本体は参照型でも、その使い方は値型的なわけで、じゃあそれをどう呼ぶかって問題かもしれません。
わたしとしては内部の動作がブラックボックス化されて、表面的に値型的な動作・使用法のみであれば、それはもう仕様として「値型」にしてほしかった、という感想です。あるいは、やはり値型とするとおかしな動作になるところも残っているのでしょうか。

つまり、プログラミングする側からとらえた場合に

string型=完全な値型

として使用してしまった場合、なにか不都合が生じるケースはあるでしょうか?







0
引用返信 編集キー/
■3855 / inTopicNo.8)  Re[6]: stringって本当に参照型?
□投稿者/ まどか 少尉(136回)-(2006/05/24(Wed) 13:41:35)

分類:[C#] 

> string型=完全な値型
> として使用してしまった場合、なにか不都合が生じるケースはあるでしょうか?

可変だからでは?

0
引用返信 編集キー/
■3857 / inTopicNo.9)  Re[7]: stringって本当に参照型?
□投稿者/ haiji 二等兵(6回)-(2006/05/24(Wed) 13:55:06)

分類:[C#] 

可変長・・・・・なるほど・・・・




0
引用返信 編集キー/
■3858 / inTopicNo.10)  Re[8]: stringって本当に参照型?
□投稿者/ 中博俊 神(450回)-(2006/05/24(Wed) 14:18:06)
中博俊 さんの Web サイト

分類:[C#] 

>しかし、System.String 自体はごく普通の参照型です。どこにも特殊なことはないと思います。

まぁ(^^;;

コンパイラの展開と、クラスの設計思想を考えればなぜそうなっているかは判断できるようになるでしょうね。

> string型=完全な値型
> として使用してしまった場合、なにか不都合が生じるケースはあるでしょうか?

値型だとかがどれほど重要なのか?ともおもいますが。

スタックに積むものはスタックの特性に配慮する必要があります。

0
引用返信 編集キー/
■3866 / inTopicNo.11)  Re[9]: stringって本当に参照型?
□投稿者/ 名無しぃシャープ 曹長(95回)-(2006/05/24(Wed) 17:24:44)

分類:[C#] 

RefEqualじゃないのに慣れるまではなんか気持ち悪くて特殊な感じがしてた。

0
引用返信 編集キー/
■3870 / inTopicNo.12)  Re[10]: stringって本当に参照型?
□投稿者/ haiji 二等兵(7回)-(2006/05/24(Wed) 20:55:15)

分類:[C#] 

みなさまありがとうございました。
また、お世話になるときはヨロシクお願いいたします。


0
引用返信 編集キー/
■4099 / inTopicNo.13)  Re[11]: stringって本当に参照型?
□投稿者/ なちゃ 二等兵(1回)-(2006/05/31(Wed) 17:26:04)

分類:[C#] 

気になったのでちょっとだけ。

> 参照型なら
> a=1 b=1 c=1
> a=2 b=2 c=2
> となるのが正しいような気がするんですが・・・・・・

正しくないです。
例1も例2も普通の参照型となんら変わらない動作です。


0
引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -