384

フィールドを外部に公開するのではなく、クラスフィールドのgetterメソッドとsetterメソッド(C#のプロパティ)を作成してカプセル化を保護する必要があるとよく言われます。

ただし、フィールドが値を保持するためだけに存在し、取得または設定するための計算を必要としない場合がよくあります。これらについては、私たち全員がこの番号を実行します。

public class Book
{
    private string _title;

    public string Title
    {
          get => _title; 
          set => _title = value;
    }
}

ええと、私には告白があります、私はそれをすべて書くことに耐えられませんでした(実際、それはそれを書く必要はなく、それを見る必要がありました)、それで私は不正に行き、公共の場を使いました。

次に、C#3.0が登場し、自動プロパティが追加されたことがわかります。

public class Book
{
    public string Title { get; set; } 
}

どちらがきれいで、私はそれに感謝していますが、実際には、単にパブリックフィールドを作成することと何がそんなに違うのですか?

public class Book
{
    public string Title;
}
4

14 に答える 14

186

少し前に私が持っていた関連する質問で、いくつかの違いを説明する、ジェフのブログへの投稿へのリンクがありました。

プロパティとパブリック変数

  • リフレクションは変数とプロパティで動作が異なるため、リフレクションに依存する場合は、すべてのプロパティを使用する方が簡単です。
  • 変数に対してデータバインドすることはできません。
  • 変数をプロパティに変更することは、重大な変更です。例えば:

    TryGetTitle(out book.Title); // requires a variable
    
于 2009-07-25T01:08:37.027 に答える
89

APIの問題を無視すると、プロパティの使用に関して私が最も価値があると思うのはデバッグです。

CLRデバッガーは、データブレークポイントをサポートしていません(ほとんどのネイティブデバッガーはサポートしています)。したがって、クラスの特定のフィールドの読み取りまたは書き込みにブレークポイントを設定することはできません。これは、特定のデバッグシナリオでは非常に制限されます。

プロパティは非常に薄いメソッドとして実装されているため、値の読み取りと書き込みにブレークポイントを設定することができます。これは彼らにフィールドの上に大きな足を与えます。

于 2009-07-25T01:22:58.123 に答える
80

フィールドからプロパティに変更すると、契約が破られます(たとえば、すべての参照コードを再コンパイルする必要があります)。したがって、他のクラス(一般に保護されている)メンバーとの対話ポイントがある場合は、将来の成長を計画する必要があります。常にプロパティを使用してこれを行います。

今日、それを自動プロパティにすることは何もありません。3か月後には、遅延読み込みを行い、ゲッターにnullチェックを入れたいと気づきます。フィールドを使用した場合、これは、アセンブリに依存している人と他の人に応じて、せいぜい再コンパイルの変更であり、最悪の場合は不可能です。

于 2009-07-25T01:07:24.593 に答える
67

誰も言及していないという理由だけで、インターフェイスでフィールドを定義することはできません。したがって、プロパティを定義する特定のインターフェイスを実装する必要がある場合、自動プロパティは非常に優れた機能である場合があります。

于 2010-09-04T01:53:38.717 に答える
53

見過ごされがちで、他のどの答えにも言及されていない大きな違い:オーバーライド。プロパティを仮想として宣言してオーバーライドできますが、パブリックメンバーフィールドに対して同じことを行うことはできません。

于 2011-09-11T21:52:27.950 に答える
12

バージョニングとAPIの安定性がすべてです。バージョン1では違いはありませんが、後で、バージョン2で何らかのエラーチェックを使用してこれをプロパティにする必要がある場合は、APIを変更する必要はありません。コードを変更する必要はありません。プロパティの定義。

于 2009-07-25T01:09:21.643 に答える
11

パブリックフィールドに対する自動実装プロパティのもう1つの利点は、セットアクセサーをプライベートまたは保護して、パブリックフィールドよりも適切に制御できるように定義されたオブジェクトのクラスを提供できることです。

于 2013-10-11T13:14:13.777 に答える
9

フィールドを作成することに何も問題はありませんpublic。ただし、フィールドを使用して作成することはカプセル化ではないことを忘れgetter/setterないでprivateください。IMO、他の機能を気にしない場合は、Propertyそれを作成することをお勧めしますpublic

于 2010-09-04T02:20:13.170 に答える
2

これらのような些細な性質は私を悲しませます。それらは最悪の種類の貨物栽培であり、C#のパブリックフィールドに対する憎悪を止める必要があります。パブリックフィールドに対する最大の議論は将来を保証することです。後でゲッターとセッターにロジックを追加する必要があると判断した場合は、フィールドを使用する他のコードで大幅なリファクタリングを行う必要があります。これは、C ++やJavaなど、getterメソッドとsetterメソッドを呼び出すためのセマンティクスが、フィールドを設定および取得するためのセマンティクスとは大きく異なる他の言語でも確かに当てはまります。ただし、C#では、プロパティにアクセスするためのセマンティクスはフィールドにアクセスするためのセマンティクスとまったく同じであるため、コードの99%はこれによる影響をまったく受けないはずです。

フィールドをプロパティに変更することを私が見た1つの例は、実際にはソースレベルでの重大な変更です。

    TryGetTitle(out book.Title); // requires a variable

これに対して、なぜTFが他のクラスのフィールドを参照として渡すのですか?プロパティではないことに応じて、ここでは実際のコーディングの失敗のように見えます。何も知らない別のクラスのデータに直接書き込むことができると仮定するのは悪い習慣です。独自のローカル変数を作成し、book.Titleそこから設定します。このようなことをするコードは、壊すに値します。

私がそれに対して見た他の議論:

  • フィールドをプロパティに変更すると、バイナリ互換性が失われ、それを使用するコードを再コンパイルする必要があります。これは、クローズドソースライブラリとして配布するコードを記述している場合の懸念事項です。その場合は、はい。ユーザー向けのクラスにパブリックフィールドがないことを確認し、必要に応じて簡単なプロパティを使用してください。ただし、99%のC#開発者のようで、プロジェクト内で純粋に内部消費するためのコードを記述している場合、なぜ再コンパイルが大きな懸念事項になるのでしょうか。他に行った変更についても再コンパイルが必要になります。再コンパイルが必要な場合はどうなりますか?最後に確認したところ、1995年ではなく、高速コンパイラとインクリメンタルリンカーを備えた高速コンピュータがあり、さらに大規模な再コンパイルには数分以上かかることはありません。「myコードのコンパイル」オフィスでの剣闘
  • 変数に対してデータバインドすることはできません。これを行う必要がある場合は、プロパティにします。
  • プロパティには、リフレクションやブレークポイントの設定など、デバッグに適した機能があります。これらのいずれかを使用する必要がある場合は、プロパティにします。デバッグが完了してリリースの準備ができたら、それらの機能がまだ必要ない場合は、フィールドに戻します。
  • プロパティを使用すると、派生クラスの動作をオーバーライドできます。このようなシナリオが発生する可能性が高いと思われる基本クラスを作成する場合は、適切なメンバーをプロパティにします。よくわからない場合は、フィールドのままにしておくと、後で変更できます。はい、それはおそらくいくつかの再コンパイルが必要になりますが、繰り返しますが、それで何ですか?

要約すると、そうです、些細なプロパティの正当な使用法がいくつかありますが、パブリックリリース用のクローズドソースライブラリを作成していない限り、フィールドは必要なときにプロパティに変換するのに十分簡単であり、パブリックフィールドに対する不合理な恐れはオブジェクト指向です私たちが自分自身を取り除くためにうまくいくであろう教義。

于 2021-10-26T06:11:24.253 に答える
1

コレクションまたはデータベースと比較することにより、タイトルが一意であることを後で確認することにした場合は、それに依存するコードを変更せずに、プロパティでそれを行うことができます。

パブリック属性のみを使用すると、柔軟性が低下します。

契約を破ることなく追加の柔軟性がプロパティの使用に関して私にとって最も重要であり、実際に柔軟性が必要になるまで、自動生成が最も理にかなっています。

于 2009-07-25T01:45:12.027 に答える
1

フィールドではできるがプロパティではできないことの1つは、フィールドを次のように指定できることです。readonly一方、プロパティはできません。したがって、フィールドは、変数がオブジェクトのインスタンス化時にのみ(コンストラクター内から)設定され、その後は変更されないという意図を明確に示す方法を提供します。はい、プロパティをプライベートセッターを持つように設定できますが、これは「これはクラスの外部から変更されない」とだけ表示されます。これは「インスタンス化後に変更されない」と同じではありません。クラス内からインスタンス化後に変更します。はい、プロパティのバッキングフィールドを読み取り専用に設定できますが、これにより、インスタンス化後の試行がコンパイル時エラーではなく実行時エラーに変更されます。したがって、読み取り専用フィールドは、プロパティでは不可能な便利なことを実行しました。

ただし、これはC#9で変更され、プロパティの次の便利な構文が得られます。

public string Height { get; init; }

これは、「これはクラスの外部から使用できますが、オブジェクトが初期化されたときにのみ設定できます」と書かれているため、Fieldsの読み取り専用の利点はなくなります。

于 2020-10-29T12:52:17.687 に答える
0

すべてのコードとテストの理由と同様に、私が非常に役立つと思うことの1つは、それがプロパティとフィールドの場合、Visual Studio IDEはプロパティの参照を表示しますが、フィールドは表示しないということです。

于 2017-06-20T03:19:55.213 に答える
0

いくつかの研究をした後の私のハメ撮り

  1. 検証。
  2. アクセサーをオーバーライドして、プロパティの動作を変更できるようにします。
  3. デバッグの目的。アクセサにブレークポイントを設定することで、プロパティがいつどのように変更されるかを知ることができます。
  4. フィールドセットのみを持つことができます。たとえば、public set()とprivate get()です。これは、パブリックフィールドでは不可能です。

それは本当に私たちにより多くの可能性と拡張性を与えてくれます。

于 2020-03-13T19:53:44.817 に答える
0

私にとって、パブリックフィールドを使用しないことの絶対的な取引ブレーカーは、IntelliSenseの欠如であり、参照を示しています。

ここに画像の説明を入力してください

これはフィールドでは使用できません。

ここに画像の説明を入力してください

于 2021-11-08T08:13:07.207 に答える