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

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

新規登録して質問してみよう
ただいま回答率
86.12%
.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

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

解決済

【C#】バッキングフィールドの必要性

SHYA181
nakamuu

総合スコア6

.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

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

5回答

2グッド

3クリップ

1312閲覧

投稿2022/11/20 06:27

バッキングフィールドの必要性

「カプセル化」に基づいてバッキングフィールドを用意して、プロパティからアクセスさせる書き方をされているのをよく見かけるのですが
以下のコードのように

特に値の変更もされずにバッキングフィールドのみがreturn、バッキングフィールドにvalueをセットしているだけ

というプロパティ

c#

1private int hoge; // バッキングフィールド 2public int Hoge 3{ 4 get 5 { 6 return this.hoge; 7 } 8 set 9 { 10 this.hoge = value; 11 } 12}


以下のような

コンパイラが自動でフィールドを用意してくれるプロパティのみの実装

と、何か違うのでしょうか?

c#

1public int Hoge { get; set ;}

以下のコードのように、プロパティ呼び出し時に値が変更されるような処理であれば、バッキングフィールドが必要なのはわかるのですが、とくに何もしていない値を返すだけのプロパティにバッキングフィールドは必要なのかどうか疑問に思いました。

c#

1private int hoge; // バッキングフィールド 2public int Hoge 3{ 4 get 5 { 6 return this.hoge + 2; 7 } 8 set 9 { 10 this.hoge = value * 2; 11 } 12}
chibahir0514, m-yatsu👍を押しています

以下のような質問にはグッドを送りましょう

  • 質問内容が明確
  • 自分も答えを知りたい
  • 質問者以外のユーザにも役立つ

グッドが多くついた質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

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

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

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

下記のような質問は推奨されていません。

  • 間違っている
  • 質問になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

適切な質問に修正を依頼しましょう。

回答5

5

ベストアンサー

おっしゃる通りバッキングフィールドの記述はコーディング上の余分に感じる作業だと思います。

という問題意識がC#開発チームにもあるようで、C#12への追加候補として半自動プロパティ (Semi auto property) の導入が検討されているようです。(詳しくは記事の方をご覧ください)

半自動プロパティ(ufcppさんの日本語解説記事)
https://ufcpp.net/blog/2021/12/semi-auto-property/

csharplangでの半自動プロパティに関する提案
https://github.com/dotnet/csharplang/issues/140

個人的な意見としては、そもそもプロパティが必要とされた背景として、「フィールドのような使い勝手だけどget時に値の評価を遅延させたり、あるいはset時に値のバリデーションや変更通知などの機能を持たせたい」という需要がありました。

特に書き換えの前と後の値がなければ値のバリデーションや変更通知が実現できないため、値の「前の状態」としてバッキングフィールドが必要なのだと考えられます。


また、半自動プロパティを提案するページのモチベーション(動機)でもバッキングフィールドについて触れられています。
https://github.com/dotnet/csharplang/blob/main/proposals/semi-auto-properties.md

標準的なオートプロパティは、バッキングフィールドを直接設定または取得することしかできず、アクセッサメソッドを変更するアクセスによってのみ何らかの制御を行うことができます。時には、標準プロパティのすべてのオーバーヘッドに直面することなく、オートプロパティにアクセスするときに何が起こるかを制御する必要がある場合があります。

よくあるシナリオは、セッターに制約を適用して、値の妥当性を確保したい場合です。もう1つは、プロパティが変更される/されたことを通知するイベントを発生させることです。

このようなケースでは、常にインスタンスフィールドを作成し、プロパティ全体を自分で記述する必要があります。これはかなりの量のコードを追加するだけでなく、フィールドが型の残りのスコープに漏れることになります。

投稿2022/11/20 08:15

tor4kichi

総合スコア748

nakamuu, chibahir0514, Zuishin, BeatStar, draq👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

回答へのコメント

SurferOnWww

2022/11/20 08:56

> 個人的な意見としては、そもそもプロパティが必要とされた背景として、「フィールドのような使い勝手だけどget時に値の評価を遅延させたり、あるいはset時に値のバリデーションや変更通知などの機能を持たせたい」という需要がありました。 オブジェクト指向の概念の一つ「カプセル化」を実現するため、通常クラス内の各フィールドへの直接アクセスは禁止するようにしておき、外部からはパブリックプロパティで各フィールドの値を取得したり設定したりするということがもともとのプロパティの目的のはずです。

3

個人的にはWPFとかで使いますね。WPFでMVVMを表現するときにデータバインディングをする際には通知をしないといけません。「フィールド IsCheckedToLock の値が変更されたよ」と通知をしてViewまたはModelに伝える必要があります。たとえば、

private bool isCheckedToLock; public bool IsCheckedToLock { get { return this.isCheckedToLock; } set { this.isCheckedToLock = value; OnPropertyChanged( "IsCheckedToLock" ); // ←これで『IsCheckedToLockが変更された』ことを通知 } }

のように通知する必要があります。

もしC#3.0で追加された自動プロパティだとデータバインドがしづらい(多分できない?)と思います。
いろんなコードを見ていてもデータバインディングしている場合は必ず昔ながらのprivateなフィールドを設けて設定や取得をしていますし。

投稿2022/11/20 08:22

BeatStar

総合スコア4953

nakamuu, umed0025, ardin👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

3

とくに何もしていない値を返すだけのプロパティにバッキングフィールドは必要なのかどうか疑問に思いました。

自分も必要なさそうに思ったのですが、ググって調べてみると Entity Framework のモデルの場合は利用価値があるそうです。

バッキング フィールド
https://learn.microsoft.com/ja-jp/ef/core/modeling/backing-field?tabs=data-annotations

"バッキング フィールドは、プロパティにではなくフィールドに対して EF が読み取りと書き込みを行うことを可能にします。 アプリケーション コードによるデータへのアクセスを制限したり、そうしたアクセスに関するセマンティクスを強化したりする目的で、クラスのカプセル化が使用されているとき、それらの制限や強化の恩恵を得ずにデータベースからの値の読み取りまたはデータベースへの値の書き込みが必要となるケースで、バッキング フィールドが役立ちます"

その記事の「フィールドとプロパティのアクセス」のセクションに書いてありますが、モデルにバッキングフィールドを定義しておくと、ModelBuilder.UsePropertyAccessMode メソッドの引数に PropertyAccessMode 列挙型を与えることで、読み取り/書き込み時にプロパティフィールドとバッキングフィールドをどのように使用するかを設定できるそうです。

PropertyAccessMode 列挙型
https://learn.microsoft.com/ja-jp/dotnet/api/microsoft.entityframeworkcore.propertyaccessmode?view=efcore-7.0

それにどういう良いことがあるのかと言われると、自分は勉強不足で具体的なメリット/デメリットは説明できませんが・・・

他にもバッキングフィールドにはこのような話があるかもしれません。

投稿2022/11/20 08:03

編集2022/11/20 08:45
SurferOnWww

総合スコア17342

nakamuu, Zuishin, BeatStar👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

3

自動プロパティはC#3.0から実装された機能で、それより前に書かれたコードだとパッキングフィールドを記述しないといけませんでした。
また、自動プロパティであっても、コンパイル時にパッキングフィールドは生成されており、プログラマーからは使用不可能という状態になっています。
そのため、実態としては同じですが、おそらくは説明のためにパッキングフィールドを明記した方が分かり易いという理由かと思います。

投稿2022/11/20 07:21

len_souko

総合スコア1307

nakamuu, Zuishin, BeatStar👍を押しています

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

0

初心者の戯言ですが…

物事を考える順序(≒コードを書いていく順序)というのが,

まずデータ(フィールド)が(必要に迫られて)存在し,→ その後で必要ならばアクセサを追加する

という感じになることが多いので,そのような特に何もしてないやつであっても自動側の記述にならないです.
(まず先に「バッキングフィールド」と呼ばれている物の側が実装されてるわけで,わざわざそれを後から自動生成してもらう記述に修正したりとかしない.)

まぁ,まともに(?)完全に設計なりを終えてから実装するならば,そんな話にはならないのでしょうけど…

投稿2022/11/23 02:49

編集2022/11/23 02:50
fana

総合スコア10641

良いと思った回答にはグッドを送りましょう。
グッドが多くついた回答ほどページの上位に表示されるので、他の人が素晴らしい回答を見つけやすくなります。

下記のような回答は推奨されていません。

  • 間違っている回答
  • 質問の回答になっていない投稿
  • スパムや攻撃的な表現を用いた投稿

このような回答には修正を依頼しましょう。

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

ただいまの回答率
86.12%

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

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

質問する

関連した質問

同じタグがついた質問を見る

.NET

.NETとは、主に.NET Frameworkと呼ばれるアプリケーションまたは開発環境を指します。CLR(共通言語ランタイム)を搭載し、入力された言語をCIL(共通中間言語)に変換・実行することが可能です。そのため、C#やPythonなど複数の言語を用いることができます。

C#

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