自動実装されたゲッターとセッターとパブリックフィールド
-
02-07-2019 - |
質問
これを行う C# クラスのコード例はたくさんあります。
public class Point {
public int x { get; set; }
public int y { get; set; }
}
または、古いコードでは、明示的なプライベート バッキング値を使用し、新しい自動実装プロパティを使用しない場合も同様です。
public class Point {
private int _x;
private int _y;
public int x {
get { return _x; }
set { _x = value; }
}
public int y {
get { return _y; }
set { _y = value; }
}
}
私の質問はその理由です。上記を実行することと、以下のように単にこれらのメンバーをパブリックフィールドにすることの間に機能的な違いはありますか?
public class Point {
public int x;
public int y;
}
誤解のないように言うと、私は基になるデータの変換を行う必要がある場合のゲッターとセッターの価値を理解しています。ただし、値を渡すだけの場合は、不必要に冗長に見えます。
他のヒント
後でこれを次のように変更することもはるかに簡単です。
public int x { get; private set; }
これらのメンバーの設定とアクセスがカプセル化されます。しばらくして、コードの開発者がメンバーにアクセスまたは設定するときにロジックを変更する必要がある場合、クラスのコントラクトを変更せずに変更を行うことができます。
この考え方は、たとえ基礎となるデータ構造を変更する必要がある場合でも、クラスへのパブリック インターフェイスを変更する必要がないということです。
C# では、プロパティと変数を異なる方法で扱うことがあります。たとえば、あなたは プロパティを ref または out パラメーターとして渡すことはできません. 。そのため、何らかの理由でデータ構造を変更する必要があり、パブリック変数を使用していてプロパティを使用する必要がある場合、インターフェイスを変更する必要があり、プロパティ x にアクセスするコードは、変数だったときのようにコンパイルできなくなる可能性があります。バツ:
Point pt = new Point();
if(Int32.TryParse(userInput, out pt.x))
{
Console.WriteLine("x = {0}", pt.x);
Console.WriteLine("x must be a public variable! Otherwise, this won't compile.");
}
最初からプロパティを使用すると、これが回避され、クライアント コードを壊すことなく、必要なだけ基礎となる実装を自由に調整できます。
Setter と Getter を使用すると、追加の抽象化レイヤーを追加できます。純粋な OOP では、オブジェクトが外部に提供しているインターフェイスを介して常にオブジェクトにアクセスする必要があります。
次のコードを考えてみましょう。これにより、asp.net に保存されますが、setter と getter によって提供される抽象化レベルがなければ実行できません。
class SomeControl
{
private string _SomeProperty ;
public string SomeProperty
{
if ( _SomeProperty == null )
return (string)Session [ "SomeProperty" ] ;
else
return _SomeProperty ;
}
}
自動実装されたゲッターは、プロパティと実際のプライベート ストレージ変数に同じ名前を取るためです。今後どのように変更できますか?ここで言われている点は、フィールドの代わりに実装された auto を使用して、将来ゲッターとセッターにロジックを追加する必要がある場合に変更できるようにするということだと思います。
例えば:
public string x { get; set; }
たとえば、x をすでに何度も使用しているため、コードを壊したくないとします。
自動ゲッターセッターを変更するにはどうすればよいですか...たとえば、setter の場合、有効な電話番号形式の設定のみを許可します...クラスのみが変更されるようにコードを変更するにはどうすればよいですか?
私のアイデアは、新しいプライベート変数を追加し、同じ x ゲッターとセッターを追加することです。
private string _x;
public string x {
get {return x};
set {
if (Datetime.TryParse(value)) {
_x = value;
}
};
}
柔軟にするとはこういうことですか?
また、バインディングとシリアル化に関して、パブリック メンバーへの変更の影響も考慮する必要があります。これらはどちらも、値の取得と設定をパブリック プロパティに依存することがよくあります。
また、ゲッターとセッターにはブレークポイントを設定できますが、フィールドには設定できません。
私の知る限り、生成されたCILインターフェイスは異なります。パブリック メンバーをプロパティに変更すると、そのパブリック インターフェイスが変更されるため、そのクラスを使用するすべてのファイルを再構築する必要があります。ゲッターとセッターの実装を変更するだけの場合、これは必要ありません。
おそらくフィールドを公開するだけで、さらに多くのことができるかもしれません 貧血ドメインモデル.
敬具
また、自動プロパティを読み取り専用にしたり、インラインで初期化したりすることはできないことにも注意してください。これらはどちらも .NET の将来のリリースで実現したいことですが、.NET 4.0 ではどちらも実行できないと思います。
最近、プロパティでバッキング フィールドを使用するのは、クラスが INotifyPropertyChanged を実装し、プロパティが変更されたときに OnPropertyChanged イベントを発生させる必要があるときだけです。
また、このような状況では、プロパティ自体を使用する場合はどこでも、コンストラクターから値が渡されるときにバッキング フィールドを直接設定します (OnPropertyChangedEvent (この時点ではいずれにしても NULL になります) を起動する必要はありません)。
後でデータの変換が必要なくなるかどうかはわかりません。メンバーを隠していれば、その準備はできています。インターフェイスは同じままであるため、翻訳を追加してもクラスのユーザーは気づきません。
最大の違いは、内部構造を変更した場合でも、API のユーザーに影響を与えることなくゲッターとセッターをそのまま維持し、内部ロジックを変更できることです。
この場合、x と y の取得方法を変更する必要がある場合は、後でプロパティを追加するだけで済みます。これが私が最も混乱させる点です。パブリック メンバー変数を使用すると、後でそれをプロパティに簡単に変更でき、値を内部に保存する必要がある場合は、_x および _y というプライベート変数を使用できます。
セッターとゲッターは原則として悪いものです (これらは OO の臭いです。実際に必要な場合もあるので、アンチパターンであるとは言いません)。
いいえ、技術的には違いはありません。最近、オブジェクトへのアクセスを本当に共有したいときは、ゲッターを追加する代わりにオブジェクトを public Final にすることがあります。
セッターとゲッターが「販売」された方法は、誰かが値を取得しているか値を変更していることを知る必要があるかもしれないということです。これはプリミティブでのみ意味を成します。
DAO、DTO、表示オブジェクトなどのプロパティ バッグ オブジェクトは、オブジェクトという言葉の実際の「OO デザイン」の意味ではオブジェクトではないため、このルールから除外されます。(DAO に「メッセージを渡す」ということは考えません。DAO は単に属性と値のペアの山です)。