私はそれが C#のフィールドとプロパティの違いは何ですか? の複製のように思えますが、私の質問にはわずかな違いがあります(私の観点から):
それを知ったら
プロパティを設定する際のある種のコントロールのように、違いはありますか(スタイル/将来の開発のものを除く)?
次の間に追加の違いはありますか?
public string MyString { get; set; }
そして
public string myString;
(最初のバージョンではC#3.0以上が必要であり、コンパイラはプライベートフィールドを作成することを認識しています。)
カプセル化。
2番目のインスタンスでは変数を定義しましたが、最初のインスタンスでは変数の周りにゲッター/セッターがあります。したがって、後日変数を検証することにした場合は、はるかに簡単になります。
さらに、IntelliSenseでの表示も異なります。
編集:更新されたOPの質問の更新-ここで他の提案を無視したい場合、他の理由はそれが単に良くないということですOOデザイン。それを行う理由はあまりありません。alwaysパブリック変数/フィールドよりもプロパティを選択してください。
フィールドとプロパティは同じように見えますが、そうではありません。プロパティはメソッドであるため、プロパティではサポートされない特定の事柄があります。また、プロパティでは発生する可能性がありますが、フィールドの場合は発生しません。
違いのリストは次のとおりです。
out/ref
引数への入力として使用できます。プロパティはできません。DateTime.Now
などのプロパティは、常にそれ自体と等しいとは限りません。readonly
にすることができます)MemberTypes
として扱われるため、異なる場所に配置されます(GetFields
vs GetProperties
など)いくつかの簡単な明らかな違い
プロパティにはアクセサーキーワードを含めることができます。
public string MyString { get; private set; }
プロパティは子孫でオーバーライドできます。
public virtual string MyString { get; protected set; }
基本的な違いは、フィールドは、指定されたタイプのデータが保存されるメモリ内の位置であるということです。プロパティは、指定された型の値を取得または設定するために実行されるコードの1つまたは2つのユニットを表します。これらのアクセサメソッドの使用は、フィールドのように動作するように見えるメンバを使用することにより、構文的に隠されています(割り当て操作の両側に表示できるという点で)。
アクセサはフィールド以上のものです。他の人はすでにいくつかの重要な違いを指摘しており、もう1つ追加します。
プロパティはインターフェイスクラスに参加します。例えば:
interface IPerson
{
string FirstName { get; set; }
string LastName { get; set; }
}
このインターフェイスは、いくつかの方法で満たすことができます。例えば:
class Person: IPerson
{
private string _name;
public string FirstName
{
get
{
return _name ?? string.Empty;
}
set
{
if (value == null)
throw new System.ArgumentNullException("value");
_name = value;
}
}
...
}
この実装では、Person
クラスが無効な状態になるのを防ぎ、呼び出し側が未割り当てプロパティからnullを取得するのを防ぎます。
しかし、設計をさらに進めることができます。たとえば、インターフェイスはセッターを処理しない場合があります。 IPerson
インターフェースのコンシューマーは、プロパティを設定することではなく、プロパティを取得することのみに関心があると言うのは非常に正当です。
interface IPerson
{
string FirstName { get; }
string LastName { get; }
}
Person
クラスの以前の実装は、このインターフェイスを満たします。呼び出し側がプロパティも設定できるという事実は、消費者(IPerson
を消費する)の観点からは無意味です。具体的な実装の追加機能は、たとえばビルダーによって考慮されます。
class PersonBuilder: IPersonBuilder
{
IPerson BuildPerson(IContext context)
{
Person person = new Person();
person.FirstName = context.GetFirstName();
person.LastName = context.GetLastName();
return person;
}
}
...
void Consumer(IPersonBuilder builder, IContext context)
{
IPerson person = builder.BuildPerson(context);
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
このコードでは、消費者はプロパティセッターを知りません。それを知ることは彼のビジネスではありません。消費者はゲッターのみを必要とし、インターフェースから、つまり契約からゲッターを取得します。
IPerson
の別の完全に有効な実装は、不変の個人クラスと対応する個人ファクトリーです。
class Person: IPerson
{
public Person(string firstName, string lastName)
{
if (string.IsNullOrEmpty(firstName) || string.IsNullOrEmpty(lastName))
throw new System.ArgumentException();
this.FirstName = firstName;
this.LastName = lastName;
}
public string FirstName { get; private set; }
public string LastName { get; private set; }
}
...
class PersonFactory: IPersonFactory
{
public IPerson CreatePerson(string firstName, string lastName)
{
return new Person(firstName, lastName);
}
}
...
void Consumer(IPersonFactory factory)
{
IPerson person = factory.CreatePerson("John", "Doe");
Console.WriteLine("{0} {1}", person.FirstName, person.LastName);
}
このコードのサンプルコンシューマでは、再びプロパティを入力する知識がありません。消費者はゲッターと具体的な実装(およびその背後にあるビジネスロジック(名前が空であるかどうかのテストなど)のみを扱う)は、特殊なクラス(ビルダーと工場)に任されています。これらの操作はすべて、フィールドではまったく不可能です。
最初の1つ:
public string MyString {get; set; }
プロパティです。 2番目(public string MyString
)はフィールドを示します。
違いは、特定の手法(インスタンス用のASP.NETデータバインディング)は、フィールドではなくプロパティでのみ機能することです。同じことがXMLシリアル化にも当てはまります。プロパティのみがシリアル化され、フィールドはシリアル化されません。
多くの場合、プロパティとフィールドは似ているように見えますが、そうではありません。フィールドには存在しないプロパティには制限があり、その逆も同様です。
他の人が述べたように。プロパティをアクセス専用にすることで、プロパティを読み取り専用または書き込み専用にできます。フィールドではできません。プロパティは仮想にすることもできますが、フィールドはできません。
プロパティをgetXXX()/ setXXX()関数の構文糖衣と考えてください。これは、それらが舞台裏で実装される方法です。
他の回答と例の中でも、この例は状況によっては役立つと思います。
たとえば、次のようなOnChange
property
があるとします。
public Action OnChange { get; set; }
デリゲートを使用する場合は、次のように変更する必要がありますOnChange
to field
public event Action OnChange = delegate {};
このような状況では、不要なアクセスや変更からフィールドを保護します。
フィールドとプロパティの間には、もう1つの重要な違いがあります。
WPFを使用する場合、パブリックプロパティにのみバインドできます。パブリックフィールドにバインドするとnotが機能します。これは、INotifyPropertyChanged
を実装していない場合でも(常にそうする必要があります)。
パブリックフィールドには、フィールドの代わりに常にプロパティを使用する必要があります。これにより、必要に応じて、既存のコードを壊すことなく、ライブラリでフィールドのカプセル化を実装できるようになります。ライブラリを使用する依存モジュールも再構築する必要があります。