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

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

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

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

Q&A

解決済

7回答

3745閲覧

C# 同クラスでは直接代入、他クラスではSetterの理由

madakko

総合スコア10

C#

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

1グッド

1クリップ

投稿2016/09/27 11:31

お世話になります。
C#のコードの書き方について質問です。

以下のような、privateフィールドと、単純なアクセサが設定されたコードがあり、

C#

1private bool flag = false; 2public bool GetFlag(){ return flag; } 3public void SetFlag(bool value){ flag = value; }

同クラス内では flag = true のような直接代入、
他クラスでは SetFlag(true) のようなアクセサで代入となっていました。

個人的にはアクセサに統一したほうが、メンテナンスしやすいと考えるのですが、このように分けて書く理由を教えたいただければ幸いです。
私としては、処理が早くなるくらいしか思いつかず。。。

どうぞよろしくお願いいたします。

【補足】
C++からの移植コードのため、プロパティとして定義されていません。

maisumakun👍を押しています

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

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

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

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

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

guest

回答7

0

ベストアンサー

こんにちは。

個人的にはアクセサに統一したほうが、メンテナンスしやすいと考えるのですが、このように分けて書く理由を教えたいただければ幸いです。

元々アクセサは、直接フィールドを設定する前や参照後に何か処理を割り込ませるために用意された仕組みです。
その処理を割り込ませたくない時には直接アクセスすることになります。

割り込ませる処理がない時でも、将来的な拡張に備えて外部I/Fについてはアクセサ経由することは多いです。
しかし、具体的にどんな処理を入れるのか見えていない時、内部アクセスをどうするべきか悩ましいです。
内部アクセスは後から変更することは容易ですし、アクセサにブレークを張ってデバッグする手法もありますから、内部からのアクセスでもアクセサ経由しておくのもありと感じます。
逆に速度を取るとか、ムダに複雑な動作をさせない等の理由で内部からはアクセサ経由しないのもありと思います。
正解はないので、あまり深く考えてても仕方がない部分かも知れません。

投稿2016/09/28 01:54

編集2016/09/28 01:56
Chironian

総合スコア23272

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

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

madakko

2016/09/28 13:09

ご回答ありがとうございます。 なるほど、とても分かりやすい理由で、とても納得できました。 確かにC++からの移植であり、変に未使用な変数なども多いので、悩んだまま現状のような作りになった可能性もあると思います。 あまり深く考えても仕方がない部分とのことで、ホッとしました。 C#では無駄な処理でもC++では意味のある処理などが多く、このような設計も何か意味があるものかと考えこんでおりました。
guest

0

移植した際にはプロパティがC#に実装されていなかったとか、Get~やSet~を使っているところの修正が大変だったとかそういった推測ができます
そこそこ新しいVisualStudioなら関数名を右クリックですべての参照を検索(だったかな?)を使うと呼び出している箇所が一気に表示されますのでちまちま置き換えるというのも可能かと思います
(その機能がなかったころの移植だと置換でやれば違うクラスの同じメンバ関数まで書き換えちゃうかもしれないので怖いという可能性があったのかと思います)
ちなみにC#のプロパティですが、内部的にはGet_プロパティ名(value)という感じで関数を作っているだけらしいので、プロパティ化しても何ら問題ないとは思われます
ちなみに強引な手段としては、Get~関数をコメントアウトして赤い波線(ビルド/コンパイルエラー)を出してIDEのエラー一覧からプロパティへ買い換えるという手もあります

投稿2016/10/01 05:56

len_souko

総合スコア1337

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

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

len_souko

2016/10/01 06:00

もとのC++で関数化して中身の書き換えを行っていたというのがどういう意図かわかりませんが、ひょっとしたら将来的にチェック機能を追加したり数値の場合は一定範囲外の場合は範囲内の抑える処理などを加える予定あるいは可能性を考慮していたのかもしれません これがpublicのフィールド(メンバ変数)だと代入する場所それぞれで値のチェックを行ってからの代入となりますので、チェック機能が変更した場合に何か所も書き換える必要があるために変更漏れが起こることを危惧したつくりであるかと思われます (ただの思い付きで決めたのかもしれませんが当事者じゃないので憶測でしか書くことはできませんが)
madakko

2016/10/03 11:06

ご回答ありがとうございます。 様々な推測、為になります。そのあたりを私一人で断言できるほど経験者ではないので、もしかしたら何かしらの深い理由があるのでは、と思い、質問させていただきました。
guest

0

引用テキストC++からの移植コードのため、プロパティとして定義されていません。

C++ の頃の名残りではないでしょうか。

もともと当該クラスでのみ使用するつもりだったんじゃないでしょうか?
なので、private で宣言。

後々、他からもアクセス可能なように public のアクセサを追加した。

投稿2016/09/28 08:04

gigamo

総合スコア12

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

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

madakko

2016/09/28 12:53

ご回答ありがとうございます。 ほかにも同様なコードがとても多いので、おっしゃる通りのような可能性も十分あると思います。 「名残りなので。」と断言できるほど、C++を経験したことがないので、今回質問させていただきました。 今後は名残りの可能性も十分考慮して理由付けしていきたいと思います。
guest

0

他の方が書かれているように、現在の C# では、自動プロパティが使えるので、単純なケースではメンバ変数はそもそも存在せずクラス内からでもプロパティを使いますね。

質問のコードのようなケースの「クラス内からは変数を直接使用する」ことに、強い意味はないと思います。
理由は上記のように、そもそもそれは自動プロパティに置き換えられる(けどしてない)ので。

弱い意味なら、心情的な「クラス内なのにプロパティを経由するのはなんかムダな気がする」程度のことかと思います。

自動プロパティが使えずメンバ変数が存在しているという事は、そのプロパティの setter/getter に何らかの副作用がある(あまりよい例ではないですが、例えばプロパティ経由でset/getするとログファイルに履歴が残る、とか)ので、副作用を起こさないようにメンバ変数を直接使う、ということはあると思います。

投稿2016/09/28 04:12

amay077

総合スコア1075

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

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

madakko

2016/09/28 13:01

ご回答ありがとうございます。 はい、新しい機能などについては、自動プロパティを使用して開発を行っています。 理由について、そこまで気にするものではないとの事で、納得できました。 副作用についても、今後考慮して行きたいと思います。 大元はCのコードだったらしく、歴史を感じさせると同時に影響範囲が未知のものとなっておりまして、副作用のような作りにまで気が回りませんでした。
guest

0

外のクラスに生のメンバ変数(フィールド)を公開しないというのは、一般に浸透しているイディオムですが、中で直接触るかどうかは企業の文化というか、それぞれのやりかたがあると思いますよ。

個人的な意見としては、
逆に中でも絶対にアクセサを使わないといけない規則だといろいろ面倒かなとは思います。
(メンバをそのままget;set;するだけのアクセサなら別に問題ないですが)
かと言って、特別な意味もなくメンバとアクセサを混同して使っているコードもちょっと嫌ですが。

投稿2016/09/28 01:42

編集2016/09/28 01:48
ishi9

総合スコア1294

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

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

madakko

2016/09/28 13:11

ご回答ありがとうございます。 今回のコードに関しては、場所や状況によりけりということですね。 私個人としては、後者の「特別な意味もなくメンバとアクセサを混同しているコード」という認識でしたので、逆のことを考えることができ、とても為になりました。
guest

0

単純に C# コンパイラが、古い時のコードじゃないですかね。

C#6以降だと、 public bool Flag { get; set; } = false; みたいに初期化もできますしね。
前は、アクセサもそのように書いてました。懐かしいです。

投稿2016/09/27 15:28

mugicya

総合スコア1046

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

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

madakko

2016/09/28 13:14

ご回答ありがとうございます。 C++からの移植コードなので、おっしゃる通り古いときのコードで、C++でのアクセサの書き方だったと思います。 C#も最初からプロパティが存在したわけではないのですね。 勉強になりました。
guest

0

私は、プロパティを使います。

C#

1public class Something(){ 2 public bool Flag{ 3 get; 4 private set; 5 } 6}

Flagはクラス内からしかセットできません。
統一感もあり、メンテしやすいです。アクセサ経由でないと触れない点も良いと思います。

プロパティの内部で例外を投げて、スタックとレースとるとわかりますが実行時はgetter,setterとして動作するようです。

投稿2016/09/27 12:35

iwamoto_takaaki

総合スコア2883

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

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

madakko

2016/09/28 13:15

ご回答ありがとうございます。 もしリファクタリングの機会があれば、プロパティ化したく思います。 C#のプロパティは自動プロパティもあって便利ですよね。 私も private set はよく使います。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.50%

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

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

質問する

関連した質問