質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

Q&A

解決済

5回答

6401閲覧

C# プロパティ 自動実装 意味は?

ElecDove

総合スコア254

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

オブジェクト指向

オブジェクト指向プログラミング(Object-oriented programming;OOP)は「オブジェクト」を使用するプログラミングの概念です。オブジェクト指向プログラムは、カプセル化(情報隠蔽)とポリモーフィズム(多態性)で構成されています。

2グッド

7クリップ

投稿2017/06/21 02:03

お世話になっております.

オブジェクト指向初心者です.
プロパティについて伺いたいのですが,

疑問①
プロパティ(アクセサ?)はクラス内部の仕様を変更したときに,外部からは全く同じように使えるようにするための余裕を残す,いわばクッションのような存在
という認識はあっていますでしょうか.


疑問②
クラス内部を絶対に変更しない場合,プロパティを使わなくてもよい?


疑問③
C#の自動実装プロパティは,「クラス内部を変更する可能性はあるからクッションは敷いておきたいけど,今のところメンバ変数の値をそのままクラス利用者に使用してほしい」というときに便利
という認識の正誤


疑問④
C#の自動実装プロパティは初期値の指定が構文で可能で,これは自動実装プロパティの時のみ有効だが,今後クラス内部の構造を変更する必要がありIIのような実装をした場合,hogeを20で(宣言と同時に)初期化することはできない
→自動実装プロパティ用の初期化構文は,疑問③の場合にのみ使えて,クラス内部の仕様を変更した場合はコンストラクタ等で別個に初期化値を代入してやらねばならない?
(メンバ変数の初期値は自動生成されるコンストラクタで代入されますよね?)

C#

1//I コンパイル可能 2public int hoge{get;set;} = 10; 3 4//II エラー 5public int hoge{ 6 get {return hoge/2;} 7 set {hoge = 2*value;} 8} = 20; 9 10 11

以上四点よろしくお願いいたします.

LouiS0616, maisumakun👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答5

0

ベストアンサー

こんにちは。
順番に回答していきます。


疑問①について、
確かにプロパティは一見クッションのように見えますが、どちらかというと、外部からのアクセスをコントロールするのはinterfaceの役割ですね。
プロパティの本当の役割は、フィールド変数の「外部から(方法を問わず)アクセスできる」という「アクセスする側に主権があるデータ管理」を、プロパティの「内部から(ときには適切な加工を経て)公開する」という「オブジェクト側に主権があるデータ管理」に変更することが目的になります。


疑問②について
違います。クラス内部の変更というのは「仕様変更」のことを言っていると思いますが、疑問①の回答で書いた通り、プロパティは「データ管理」の責任の所在を明確にするためのものです。どのような状況でも基本的にプロパティを使うべきです。


疑問③について
確かに自動実装は素通しですが、ほとんどの場合setterを外部に公開することはなく、getterのみを公開することが多いです。setterを自動実装で公開する場合は、enum型など「データ型自体に制約がついているもの」を指定することが多いイメージです。
認識としては、「オブジェクトが何らかのデータを公開する」場合は全てプロパティとして公開し、フィールド変数を直接公開することはしない。そして、内部の変数をそのまま公開すればよい場合は自動実装でも問題がないだけである、と考えてしまって問題ないです。


疑問④について
自動実装の初期化構文は「getter-onlyの自動実装プロパティ」と同時に導入されたもので、威力を発揮する場面は限られます。結局のところ、インスタンス生成時にコンストラクタの先頭で代入される動作に近いもので、単に「特定の状況で楽に書ける糖衣構文」でしかないのです。

投稿2017/06/21 02:27

編集2017/06/21 02:33
tamoto

総合スコア4103

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ElecDove

2017/06/21 22:56

回答ありがとうございます. >プロパティの本当の役割は、フィールド変数の~~~に変更することが目的になります。 そういうことだったんですね!勘違いしておりました >認識としては~~~問題ないです どうしてもプロパティを書くのが面倒くさくてさぼりたくなってしまいますが笑 そういうときのために自動実装が導入されたんですね たしかに,毎回Set〇〇とかやるのと比べると労力が全然… >威力を発揮する場面は限られます。 おかげさまで疑問がすっきりしました
guest

0

既にいろいろ回答がされていますが、自分も書いておきます。参考になれば幸いです。

疑問①
「余裕を残す、いわばクッション」という表現が自分にはピンときませんが・・・

オブジェクト指向の概念の一つ「カプセル化」を実現するため、通常クラス内の各フィールドへの直接アクセスは禁止するようにしておき、外部からはパブリックプロパティで各フィールの値を取得したり設定したりするということがもともとの目的のはずです。

「カプセル化」の結果として、質問者さんが言われる「クラス内部の仕様を変更したときに,外部からは全く同じように使えるようにする」ことが可能になるということだと思います。

疑問②
プロパティを使う目的には、開発者が意図した規則に基づいてフィールドを正しく使用できるよう保証するということもあります。それは、質問者さんが言われる「クラス内部を絶対に変更しない場合」とは関係ないですよね。

例えば、以下の記事ように、ユーザーが Visual Studio でプロパティを設定する際、範囲外であると例外をスローするようなこともできます。

Web Custom Control の例外処置
http://surferonwww.info/BlogEngine/post/2010/08/06/Exception-handling-by-web-custom-control.aspx

疑問③④
自動実装プロパティを利用する意味は、プログラミングガイドに書いてありますが、"プロパティ アクセサーに追加のロジックが必要ない場合は、プロパティをより簡潔に宣言できます" ということに尽きると思います。

例えば、最近の Entity Framework Code First でのモデルの定義に使うようなケース(下記記事参照)で有用だと思います。

新しいデータベースの Code First
https://msdn.microsoft.com/ja-jp/data/jj193542.aspx

投稿2017/06/21 03:28

退会済みユーザー

退会済みユーザー

総合スコア0

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ElecDove

2017/06/21 23:01

回答ありがとうございます >ユーザーが Visual Studio でプロパティを設定する際、範囲外であると例外をスローするようなこともできます。 確かにこれは必要ですね そう考えると,プロパティはなくてはならないものだと思えます
guest

0

1 あってる。
2 間違い。「すべての」外部からクラスにアクセスするとき、プロパティを使う。
3 必ずプロパティを作らないとだめだけど、記述が長くてだるいが、自動実装を使うと記述が短くなって楽ちん
4 昔ながらのプロパティの実装をすればいい。

private int hoge = 20 public int Hoge{ get {return hoge/2;} set {hoge = 2*value;} };

プロパティを作るのに、フィールド用の変数と、get,setを書かないとだめで、変数をそのまま渡すとき、記述が長くてだるかった。

余計なことを考えずに、必ずプロパティを使う。ということだけ覚えておけばいいと思います。
必ずプロパティだけど、記述が増えるのが面倒だったので、省略記法を作ったと。

投稿2017/06/21 02:50

編集2017/06/21 02:57
kiichi54321

総合スコア1984

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ElecDove

2017/06/21 23:00

回答ありがとうございます > 昔ながらのプロパティの実装をすればいい。 そういうものなのですね 余りオブジェクト指向に慣れていないせいか, 変数_Hogeと プロパティHogeがあるのってなんか冗長だなぁ,,,もっとすっきり書かせてくれないかなぁ,なんて思ってしまいますが
guest

0

こんにちは。

まず、大きな勘違いがあると思います。プロパティはアクセサと似た機能を提供しますが、その主目的はアクセサではありません。

疑問①

プロパティがないJavaなどで使われるアクセサ(getXxx, setXxx)がこれに合致します。
しかし、元々プロパティはGUI開発ツールで例えばWidth=640;としただけでウィンドウの幅を変えることができるような機能を実装するために提案された機能です。(私の知る範囲ではVisual Basicが最初です。)

疑問②

クラス内部を変更する予定がない時、フィールドを直接公開していたと仮定します。
ある日、フィールドの仕様を変更して倍の値を保持するようにしました。
その時、フィールド名を変更し、元のフィールド名のプロパティを実装することでこの仕様変更を外部に波及させないで済むと言う使い方ができます。

他にはset/getにブレークを張ってデバッグするとか、ログを仕込む等のデバッグにも有用と思います。

疑問③

setをprivateにするなどして、リードオンリな「メンバ変数」を実装する際に便利と思います。

疑問④

ごめんなさい。その辺は把握していません。


オブジェクト指向プログラミングでは「メンバ変数」はできるだけprivateにすることが推奨されます。
そのprivateにする主旨を理解しないまま、フィールドを直接公開することは悪で関数(アクセサ)を介して公開するのは問題ないと理解している人達が少なくありませんのでご用心。

できるだけメンバ変数をprivateにした方が良い理由は「疑問①」に書かれた通りですが、オブジェクト指向プログラミング的にはメンバ変数をそのままset/getするケースは稀です。そのようなメンバ変数が多数発生する場合はクラス設計に問題が潜んでいる可能性が高いてす。
つまり、プロパティを「疑問①」の目的で使うケースもありますが、それが頻発するクラスは何か設計上の問題を抱えています。これはプロパティの主目的ではありません。単なる副産物です。

投稿2017/06/21 02:39

編集2017/06/21 03:42
Chironian

総合スコア23272

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ElecDove

2017/06/21 22:59

回答ありがとうございます >元々プロパティはGUI開発ツールで例えばWidth=640;~~~機能を実装するために提案された機能です。 なるほど! ただの代入だったら変更を監視するか何かしないと幅変わりませんね ところで,そうだとすると例えば .ChangeWidth(640)と何が違うのでしょうか 見た目が違うだけですか? >ログを仕込む等のデバッグにも有用と思います。 確かに非常に便利です >そのようなメンバ変数が多数発生する場合はクラス設計に問題が潜んでいる可能性が高いてす。 もう少し調べたいと思います
Chironian

2017/06/22 01:43

> 例えば .ChangeWidth(640)と何が違うのでしょうか 取り出す時もint w=form.Width;でできますよ。覚えることが少ないし、直感的な操作です。 でも、ま、それだけではあります。だからと思いますが、Javaはプロパティをサポートしていないようです。
ElecDove

2017/06/23 12:55

>でも、ま、それだけではあります。 そう考えると納得しました プロパティが存在することに(Javaなどのアクセサと比べて)「便利」とか「使いやすい」以上の機能はないのですね とはいえせっかくあるので,アクセサ用のメソッドを作らずプロパティで対応したいと思います.
guest

0

私の考えですが、プログラムは正しく動作することが正しいので書き方はそれそぞれでよいと思います。ただ、それぞれの書き方には利点があり、それを理解して使った方が素早くより正しく動作するプログラムが書けると考えています。

C#も正しさより、良いやり方を提案しつつ、ユーザーに任せてくれるのが良い部分だと思いますので、ご自身がよいと思われる方法を選んでください。

疑問①

プロパティ(アクセサ?)はクラス内部の仕様を変更したときに,外部からは全く同じように使えるようにするための余裕を残す,いわばクッションのような存在
という認識はあっていますでしょうか.

私もクッションと考えています。

疑問②

クラス内部を絶対に変更しない場合,プロパティを使わなくてもよい?

使って問題なければ、使って問題ないでしょうね。特に、DBのレコードをデータを保持するだけのロジックのないオブジェクトであればそれで良いかもしれません。ただ、オブジェクト指向的には、内部処理との問題を気にする必要が無いようにプロパティを使うのがおススメです。(プロジェクトによって考え方があってもいいと思います。)

疑問③

C#の自動実装プロパティは,「クラス内部を変更する可能性はあるからクッションは敷いておきたいけど,今のところメンバ変数の値をそのままクラス利用者に使用してほしい」というときに便利
という認識の正誤

私はprivateのメンバ変数にもプロパティを使います。場合によっては内部の仕様変更でも、メンバ変数の出し入れの前後に処理を挟む事を思いつくこともあるからです。(それでも、ややこしいときは変数を管理するinnerClassを定義します。)

疑問④

C#の自動実装プロパティは初期値の指定が構文で可能で,これは自動実装プロパティの時のみ有効だが,今後クラス内部の構造を変更する必要がありIIのような実装をした場合,hogeを20で(宣言と同時に)初期化することはできない

確かにできたら便利そうですが、例示の書き方だと変数の名称と代入が離れていてわかりずらく見えます。また、hogeを再帰的に検索するのが正しい動きに見えます。
シンタックスシュガーを用いない方法がとりあえず良いのではないでしょうか?

投稿2017/06/21 04:10

iwamoto_takaaki

総合スコア2883

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ElecDove

2017/06/23 12:57

回答ありがとうございます. >特に、DBのレコードをデータを保持するだけのロジックのないオブジェクトであればそれで良いかもしれません。 何が何でもプロパティを使わなければならないとは限らない場面もあるということなのですね まだ私は遭遇していないため実感がわきませんが,頭の片隅に置いておきたいと思います. >場合によっては内部の仕様変更でも、メンバ変数の出し入れの前後に処理を挟む事を思いつくこともあるからです。 まさにおっしゃる通りだと思いました
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問