🎄teratailクリスマスプレゼントキャンペーン2024🎄』開催中!

\teratail特別グッズやAmazonギフトカード最大2,000円分が当たる!/

詳細はこちら
.NET

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

C#

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

Q&A

解決済

5回答

3528閲覧

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

SHYA181

総合スコア6

.NET

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

C#

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

2グッド

3クリップ

投稿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👍を押しています

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

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

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

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

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

guest

回答5

0

ベストアンサー

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

という問題意識が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

総合スコア769

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

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

退会済みユーザー

退会済みユーザー

2022/11/20 08:56

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

0

個人的には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

総合スコア4962

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

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

0

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

自分も必要なさそうに思ったのですが、ググって調べてみると 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
退会済みユーザー

退会済みユーザー

総合スコア0

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

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

0

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

投稿2022/11/20 07:21

len_souko

総合スコア1363

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

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

0

初心者の戯言ですが…

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

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

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

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

投稿2022/11/23 02:49

編集2022/11/23 02:50
fana

総合スコア11990

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.36%

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

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

質問する

関連した質問