- PR -

propertyにstructが使えるのか

1
投稿者投稿内容
Tacchang
ベテラン
会議室デビュー日: 2004/09/05
投稿数: 55
お住まい・勤務地: 川崎市
投稿日時: 2005-08-05 10:48
みなさん,こんにちは.
#先日はdelegateの件ありがとうございました.
structでpropertyを作成するケースについて確認したいことがあって投稿させて頂きます.

「C#には,structがあってスタック領域に実体が確保される.ヒープ領域に実体を作るよりコストがかからない」という説明をいくつかの場所で拝見しました.また,クラスを設計する場合(私の場合C++でしたが),値型と参照型は区別して定義した方がよい(==演算子の意味など)ということを
株式会社 オージス総研 伊藤 喜一様,
http://www.ogis-ri.co.jp/otc/hiroba/technical/CppDesignNote/index.html
で知り「仰る通り」と思ってそういうクラス設計をしてきました.

そこで私は単純に値型の場合は全てstructにしようと思ったのですが,
日本ユニシス株式会社,「.NET的視点」, 尾島 良司様
http://www.unisys.co.jp/club/net_view/20030127.html

Holder.Property.Value = 10; // 適当な例です
ができないことを教えていただきました(もちろん試すとその通り).尾島様の仰る通り『「なんだかわからないけどコンパイルできない」なんていう地獄がここで発生』している状態です.

Q1.classによるpropertyのような使い方を期待することはできないものなのでしょうか.それとも,structによるpropertyのset/getの書き方で解決するものなんでしょうか(object型の器に入れておく?structのメリットが無くなる?).

Q2.Holder.Property = NewProperty;ができて,Holder.Property.Value = 10;という書き方ができないのでしょうか.structであることが原因であれば,両者ともNGになる気がします.前出した.NET的視点で尾島様が解説をしてくださっていますが,残念ながらその内容が理解できません.

Q3.class内に含まれているstructはどのようなスタック領域に作成されるのでしょうか.包含しているclassがnewされたスコープ内でしょうか.もしそうだとすると,newされたクラスをスコープ外へ渡すようなコードを書いた場合,C#コンパイラがclass内のstructをコピーしてくれるのでしょうか.

Q4.MSDNのサンプルをちらっと(例えばControl.Location)見ると,『〜は値型であるため、値で返されます.プロパティを調整しても、各プロパティ値に影響はありません』という記述がありますが,利用者はプロパティがstructかclassか判った上で利用しなければならないということでしょうか.もしそうだとすると,MSDNのようにきっちりドキュメントを書くか,利用者側のスキルがある一定レベル以上でなければならない,ということでしょうか.C++やJavaだと,structだからどうとか(Javaにはありませんね)classだからどうとかないと思いますが,C#ではこの点に気を付ける必要があると言うことでしょうか.
Hongliang
ぬし
会議室デビュー日: 2004/12/25
投稿数: 576
投稿日時: 2005-08-05 11:30
引用:
Q1.classによるpropertyのような使い方を期待することはできないものなのでしょうか.それとも,structによるpropertyのset/getの書き方で解決するものなんでしょうか(object型の器に入れておく?structのメリットが無くなる?).


"classによるpropertyのような使い方"というのがどんな使い方なのか知りませんが、それがもし"「プロパティが示すインスタンス」が持つプロパティの値を直接設定する"という事なのであれば、それは確かに不可能です。

引用:
Q2.Holder.Property = NewProperty;ができて,Holder.Property.Value = 10;という書き方ができないのでしょうか.


Holder.Propertyが構造体インスタンスを返す場合、構造体=値型は値のコピーを返します。端的に言うのなら、バイトデータの塊をコピーして返します。
既に値はコピー済みであり、コピー先でどう変更したところでコピー元には何の影響もありません。
つまり、
コード:
class Holder {
    private Property property;
    public Property Property {
        get {return property;}
        set {property = value;}
    }
}

というHolderクラスにおいて、Holderが保持するpropertyフィールドと、Propertyプロパティが返すPropertyインスタンスは、値は同じですがコピーされた別物であると言うことです。

引用:
structであることが原因であれば,両者ともNGになる気がします.


何故でしょう?
Holder.Property = new Property();
これはPropertyインスタンスを作り、そのコピーをHolder.Propertyに設定しています。
newされたインスタンスと実際にpropertyフィールドに代入されるインスタンスはコピーされた別物ですが、値は同じです。

引用:
Q3.class内に含まれているstructはどのようなスタック領域に作成されるのでしょうか.


クラスインスタンスに存在する値型のフィールドは、そのインスタンスが存在するヒープ領域に確保されたはずです。

引用:
Q4.MSDNのサンプルをちらっと(例えばControl.Location)見ると,『〜は値型であるため、値で返されます.プロパティを調整しても、各プロパティ値に影響はありません』という記述がありますが,利用者はプロパティがstructかclassか判った上で利用しなければならないということでしょうか.もしそうだとすると,MSDNのようにきっちりドキュメントを書くか,利用者側のスキルがある一定レベル以上でなければならない,ということでしょうか.C++やJavaだと,structだからどうとか(Javaにはありませんね)classだからどうとかないと思いますが,C#ではこの点に気を付ける必要があると言うことでしょうか.


確かにそれが値型かどうか気を付ける必要はあります。
しかし、値型プロパティのそのプロパティを操作するようなコードはコンパイルエラーを出すのですから、そこがバグの元にはならないでしょう。初心者には確かに意味不明のコンパイルエラーと映るでしょうから、そこをどうするかは教育する側の課題ですね。
しかし逆に、参照型のプロパティであっても、そのプロパティが返す値が毎回newされたインスタンスであるという可能性はあります。この場合、直接プロパティのプロパティを操作できるのに設定が反映されないと言うバグの元になります。
//そんな事する奴がいるものかと思ってしまいますが、実際に.NET Frameworkのライブラリの中にも存在します。System.Drawing.ImageクラスのPaletteプロパティがそうでした。
よねKEN
ぬし
会議室デビュー日: 2003/08/23
投稿数: 472
投稿日時: 2005-08-06 02:02
引用:

引用:
Q4.MSDNのサンプルをちらっと(例えばControl.Location)見ると,『〜は値型であるため、値で返されます.プロパティを調整しても、各プロパティ値に影響はありません』という記述がありますが,利用者はプロパティがstructかclassか判った上で利用しなければならないということでしょうか.もしそうだとすると,MSDNのようにきっちりドキュメントを書くか,利用者側のスキルがある一定レベル以上でなければならない,ということでしょうか.C++やJavaだと,structだからどうとか(Javaにはありませんね)classだからどうとかないと思いますが,C#ではこの点に気を付ける必要があると言うことでしょうか.



確かにそれが値型かどうか気を付ける必要はあります。
しかし、値型プロパティのそのプロパティを操作するようなコードはコンパイルエラーを出すのですから、そこがバグの元にはならないでしょう。初心者には確かに意味不明のコンパイルエラーと映るでしょうから、そこをどうするかは教育する側の課題ですね。



値型のメソッドを使っても警告すらでないので、
バグの元になりやすいと思います。面倒ごとが多いだけで
大してメリットがあるとも思わないので、APIのパラメータで
使うなどのごく限られた状況でしか構造体は使いませんね。

#FormのDesktopLocationプロパティにOffsetメソッドを使ってはまった経験あり。
ほげた
ベテラン
会議室デビュー日: 2002/05/08
投稿数: 67
お住まい・勤務地: なごやん
投稿日時: 2005-08-07 07:03
値型と参照型の振る舞いの違いは、やっかいなバグを埋め込んで
生産性が低下する可能性がありますね。
ボクシングの発生によるパフォーマンス低下も怖いです。

そんなわけで、開発チームでは struct を使用禁止にしてます。
#クラス内の非公開な struct のみ可

メンバのスキルが安心できるほどあれば、うまく使えるのかとも思いますが
将来、どんなメンバが追加投入されるかもわかりませんし・・・

リスクをとるほどのメリットが struct には無い気がします。
Tacchang
ベテラン
会議室デビュー日: 2004/09/05
投稿数: 55
お住まい・勤務地: 川崎市
投稿日時: 2005-08-07 20:44
Hongliangさん、よねKENさん、ほげたさん、コメントありがとうございます。
個人的な趣味でプログラムを作成する場合はstructを使うことに何の躊躇もありませんが、仕事となるとやっぱり心配ですね。
仕事では、いろんなスキルの人間が集まりますから、ほげたさんの仰るようにフレームワーク(スキルの高い人が作る基盤プログラムという意味で使っています)以外で使用禁止、非公開ならば使用可という制約を設けた方が幸せになれそうです。
C#で作るプログラム(システム)で、ヒープを使うオーバヘッドが問題になるケースはあまりなさそうですからね。
参考になりました。
1

スキルアップ/キャリアアップ(JOB@IT)