カプセル化とは、オブジェクトの状態が定義されたインターフェースを介してのみ発生することを意味します。これにより、クラスはこの状態が常に有効であり、クラスの目的に沿っていることを確認できます。
したがって、場合によっては、フィールドをパブリックに公開することはカプセル化の原則に完全に準拠しています。フィールドのすべての可能な値は、他のすべてのフィールドの可能なすべての値で有効であり、プログラマはフィールドを許可することを積極的に決定できます。外部のコードによって自由に操作されます。
これらのケースは、ほとんどが「単純な古いデータ」であるクラスにほとんど制限されています。彼らはまた、この点であまり興味深いものではないので、それらについては十分です。
他の場合では、他の言語ではint getId()、値を取得しvoid setId(int val)て更新するような、getterおよびsetterメソッドがあります。
プロパティを使用すると、フィールドの読み取りと書き込みに使用するのと同じ構文を、そのようなメソッドを介した読み取りと書き込みに使用できます。これは重要ではありませんが、良い構文上の砂糖です。
(実際には、リフレクションが機能する方法とDataBinder.Eval、フィールドが正常に機能する場合でもプロパティを持つと便利な場合もありますが、それは別の問題です)。
プライベートセッターが導入されるまで(実際には、C#2で変更されたのは、同じブロックにプライベートセッターとパブリックまたは保護されたゲッターを含めるための構文です)、プライベートセッターの処理を実行するプライベートメソッドがありました。プライベートセッターは実際には必要ありません。ただし、これらは便利なので、構文上の砂糖だけですが、かなり便利です。
カプセル化は、セッター(またはゲッター)がパブリック、プライベート、保護、内部のいずれであるかではなく、適切かどうかの問題です。すべてのフィールドのデフォルトがプライベートである(そしてその点についてreadonly)から始め、必要に応じて、それらのフィールドを変更するメンバー(プロパティまたはメソッド)を追加し、オブジェクトが変更されても有効であることを確認します。これにより、クラスの不変条件が維持されます。つまり、クラスが持つことができる有効な状態のセットを記述するルールが破られることはありません(コンストラクターがそのような有効な状態で開始することを確認することによっても役立ちます)。
あなたの最後の質問については、クラスが何のパブリック、保護または内部セッター持っていないことを不変の手段であるとし、無公共、保護または任意のフィールドを変更内部メソッドを。これには次の程度があります。C#では、次の3つの程度が可能です。
クラスのすべてのインスタンスフィールドはreadonlyであるため、プライベートコードでも変更できません。これは不変であることが保証されており(変更しようとしてもコンパイルされません)、これに基づいて最適化を行うことができます。
パブリックメンバーは何も変更しないため、クラスは外部から不変ですがreadonly、内部から変更されないことを保証するものではありません。
一部の状態は実装の詳細として変更されていますが、クラスは外部から見ると不変です。たとえば、フィールドをメモ化できるため、外部からフィールドを取得しようとすると同じ値が取得されるだけですが、最初のそのような試行では実際にフィールドが計算され、その後の試行で取得できるように格納されます。
private File settingsFile = null;なり、さらにコンストラクタの1つでそれを行うこともできなくなりますif (settingsFile == null) { settingsFile = GetSettingsFile() };。そのようなコードをリファクタリングすると、時々私は泣きました:) コンストラクタの前にメンバーを設定できるからといって、複数のコンストラクタを使用する必要があるという意味ではありません。これは、ロジックに従うのが困難になるためです。プライベートセッターは、コンストラクター内または後で値を設定するように強制します。