web-dev-qa-db-ja.com

フィールドとプロパティの違いは何ですか?

C#では、フィールドがプロパティと異なるのはなぜですか。また、プロパティの代わりにフィールドを使用する必要があるのはいつですか。

961
Anonymous

プロパティはフィールドを公開します。フィールドは(ほとんどの場合)クラスに対して非公開にし、getおよびsetプロパティを介してアクセスする必要があります。プロパティは抽象化のレベルを提供し、クラスを使用することによって外部フィールドにアクセスする方法に影響を与えずにフィールドを変更することを可能にします。

public class MyClass
{
    // this is a field.  It is private to your class and stores the actual data.
    private string _myField;

    // this is a property. When accessed it uses the underlying field,
    // but only exposes the contract, which will not be affected by the underlying field
    public string MyProperty
    {
        get
        {
            return _myField;
        }
        set
        {
            _myField = value;
        }
    }

    // This is an AutoProperty (C# 3.0 and higher) - which is a shorthand syntax
    // used to generate a private field for you
    public int AnotherProperty{get;set;} 
}

@Kentは、Propertiesはフィールドをカプセル化するために必須ではなく、他のフィールドで計算を行ったり、他の目的を果たすことができると指摘しています。

@GSSは、検証、プロパティにアクセスしたときの検証など、他の便利な機能も実行できることを指摘しています。

845
Cory

オブジェクト指向プログラミングの原則によると、クラスの内部動作は外部から隠されるべきです。フィールドを公開する場合は、本質的にクラスの内部実装を公開しています。したがって、フィールドをProperties(またはJavaの場合はメソッド)でラップして、コードを壊すことなく実装を変更できるようにします。プロパティにロジックを入れることができるので、必要に応じて検証ロジックなどを実行することもできます。 C#3には、autopropertiesという混乱を招く可能性があります。これにより、Propertyを簡単に定義でき、C#3コンパイラによってプライベートフィールドが生成されます。

public class Person
{
   private string _name;

   public string Name
   {
      get
      {
         return _name;
      }
      set
      {
         _name = value;
      }
   }
   public int Age{get;set;} //AutoProperty generates private field for us
}
231
danswain

重要な違いは、インタフェースはプロパティを持つことができますがフィールドを持つことはできないということです。これは、私にとっては、フィールドはクラスのプライベートな内部動作で使われることを意図しているのに対し、プロパティはクラスのパブリックインタフェースを定義するために使われるべきであることを強調しています。原則として、私はパブリックフィールドを作成することはめったになく、同様に私は非パブリックプロパティを作成することもほとんどありません。

147
Hans Løken

歯車が回転する可能性があるプロパティの使用例をいくつか紹介します。

  • Lazy Initializationロードするのが高価であるが、通常のコード実行ではそれほどアクセスされないオブジェクトのプロパティがある場合は、次のようにしてロードを遅らせることができます。財産。そのようにして、ただそこに座っているだけですが、別のモジュールがそのプロパティを呼び出そうとするときに、基礎となるフィールドがnullかどうかをチェックします。これにより、オブジェクトの初期化が大幅にスピードアップします。
  • ダーティートラッキング: StackOverflowの 自分の質問 から実際に学んだこと。実行中に値が変更された可能性があるオブジェクトが多数ある場合は、プロパティを使用してそれらをデータベースに保存し直す必要があるかどうかを追跡できます。オブジェクトの単一のプロパティが変更されていない場合、IsDirtyフラグは作動しません。そのため、データベースに戻す必要があると判断したときに、保存機能はそれをスキップします。
91
Chris

プロパティを使用すると、プロパティの値が変更されたとき(別名PropertyChangedEvent)、またはキャンセルをサポートするために値が変更される前に、イベントをスローできます。

これは(直接アクセスする)フィールドでは不可能です。

public class Person {
 private string _name;

 public event EventHandler NameChanging;     
 public event EventHandler NameChanged;

 public string Name{
  get
  {
     return _name;
  }
  set
  {
     OnNameChanging();
     _name = value;
     OnNameChanged();
  }
 }

 private void OnNameChanging(){
   EventHandler localEvent = NameChanging;
   if (localEvent != null) {
     localEvent(this,EventArgs.Empty);
   }
 }

 private void OnNameChanged(){
   EventHandler localEvent = NameChanged;
   if (localEvent != null) {
     localEvent(this,EventArgs.Empty);
   }
 }
}
46
Jehof

彼らの多くはPropertiesFieldの技術的な長所と短所を説明してきたので、今度はリアルタイムの例に入る時間です。

1.プロパティで読み取り専用アクセスレベルを設定できます

dataTable.Rows.CountdataTable.Columns[i].Captionの場合を考えます。それらはクラスDataTableから来ていて、どちらも私たちに公開されています。それらに対するアクセスレベルの違いは、valueをdataTable.Rows.Countに設定することはできませんが、dataTable.Columns[i].Captionに読み書きすることはできるということです。それはFieldを通して可能ですか?いいえ!これはPropertiesでのみ可能です。

public class DataTable
{
    public class Rows
    {       
       private string _count;        

       // This Count will be accessable to us but have used only "get" ie, readonly
       public int Count
       {
           get
           {
              return _count;
           }       
       }
    } 

    public class Columns
    {
        private string _caption;        

        // Used both "get" and "set" ie, readable and writable
        public string Caption
        {
           get
           {
              return _caption;
           }
           set
           {
              _caption = value;
           }
       }       
    } 
}

2. PropertyGridのプロパティ

Visual StudioでButtonを使ったことがあるかもしれません。そのプロパティはPropertyGridTextなどのようにNameに表示されます。ボタンをドラッグアンドドロップしてプロパティをクリックすると、自動的にクラスButtonとフィルタPropertiesが表示され、PropertyGridに表示されます(PropertyGridは表示されません)。たとえ公開されていてもField

public class Button
{
    private string _text;        
    private string _name;
    private string _someProperty;

    public string Text
    {
        get
        {
           return _text;
        }
        set
        {
           _text = value;
        }
   } 

   public string Name
   {
        get
        {
           return _name;
        }
        set
        {
           _name = value;
        }
   } 

   [Browsable(false)]
   public string SomeProperty
   {
        get
        {
           return _someProperty;
        }
        set
        {
           _someProperty= value;
        }
   } 

PropertyGridでは、プロパティNameTextは表示されますが、SomePropertyは表示されません。なぜ???プロパティは 属性 を受け入れることができるからです。 [Browsable(false)]がfalseの場合は表示されません。

3.プロパティ内で文を実行できます

public class Rows
{       
    private string _count;        


    public int Count
    {
        get
        {
           return CalculateNoOfRows();
        }  
    } 

    public int CalculateNoOfRows()
    {
         // Calculation here and finally set the value to _count
         return _count;
    }
}

4.バインド元ではプロパティのみ使用可能

Binding Source コードの行数を減らすのに役立ちます。 FieldsBindingSourceには受け入れられません。そのためにはPropertiesを使うべきです。

5.デバッグモード

値を保持するためにFieldを使用しているとします。ある時点で、そのフィールドの値がnullになっている箇所をデバッグして確認する必要があります。コードの行数が1000を超える場合は、実行が困難になります。このような状況では、Propertyを使用してProperty内でデバッグモードを設定できます。

   public string Name
   {
        // Can set debug mode inside get or set
        get
        {
           return _name;
        }
        set
        {
           _name = value;
        }
   }
41
Sarath Avanavu

違い - 使用方法(いつ、なぜ)

field は、クラスまたは構造体で直接宣言されている変数です。クラスまたは構造体は、インスタンスフィールドまたは静的フィールド、あるいはその両方を持つことができます。一般的に、フィールド は、プライベートまたは保護されたアクセシビリティ を持つ変数に対してのみ使用してください。あなたのクラスがクライアントコードに公開するデータ はメソッド、プロパティ そしてインデクサーを通して提供されるべきです。これらの構成を内部フィールドへの間接アクセスに使用することで、無効な入力値から保護することができます。

property は、プライベートフィールドの値を読み取り、書き込み、または計算するための柔軟なメカニズムを提供するメンバーです。プロパティは、あたかもパブリックデータメンバであるかのように使用できますが、実際は アクセサ という特別なメソッドです。これはデータに簡単にアクセスすることを可能にし、それでも 安全性とメソッドの柔軟性 を促進するのを助けます。プロパティを使用すると、実装または検証コードを隠しながら、クラスが値を取得および設定する一般的な方法を公開できます。プロパティ値を返すにはget propertyアクセサを使用し、新しい値を割り当てるにはsetアクセサを使用します。

28
makiSTB

プロパティには、パブリックインタフェースを壊さずにオブジェクト上のデータへのアクセス方法を変更できるという主な利点があります。たとえば、検証を追加する必要がある場合、または格納されているフィールドを計算式に変更する必要がある場合は、最初にフィールドをプロパティとして公開していれば簡単に実行できます。フィールドを直接公開したばかりの場合は、新しい機能を追加するためにクラスのパブリックインタフェースを変更する必要があります。その変更は既存のクライアントを破壊し、新しいバージョンのコードを使用する前にそれらを再コンパイルする必要があります。

幅広い用途に設計されたクラスライブラリ(何百万もの人々によって使用されている.NET Frameworkなど)を書く場合、それは問題になる可能性があります。しかし、小さいコードベースの内部で使用されるクラス(たとえば、50 K行以下)を書いているのであれば、大したことはありません。その場合、それは本当に個人的な好みに帰着します。

10

バックグラウンドでは、プロパティはメソッドにコンパイルされます。そのためNameプロパティはget_Name()set_Name(string value)にコンパイルされます。あなたがコンパイルされたコードを研究すればこれを見ることができます。そのため、それらを使用すると(非常に)小さなパフォーマンスオーバーヘッドがあります。通常、フィールドを外部に公開する場合は常にプロパティを使用し、値の検証を行う必要がある場合は内部的に使用することがよくあります。

8
Rune Grimstad

プロパティは非対称アクセスをサポートしています。つまり、ゲッターとセッターのどちらか、または2つのうちの1つのみを持つことができます。同様に、プロパティはgetter/setterに対する個々のアクセシビリティをサポートしています。フィールドは常に対称的です。つまり、いつでも値を取得および設定できます。これに対する例外は読み取り専用フィールドであり、明らかに初期化後に設定することはできません。

プロパティは非常に長時間実行され、副作用があり、さらに例外をスローすることさえあります。フィールドは高速で、副作用もなく、例外をスローすることもありません。副作用のため、プロパティは各呼び出しに対して異なる値を返す可能性があります(DateTime.Nowの場合のように、つまりDateTime.Nowが常にDateTime.Nowと等しいとは限りません)。フィールドは常に同じ値を返します。

フィールドはout/refパラメータに使用できますが、プロパティは使用できません。プロパティは追加のロジックをサポートします - これは他のものの間で遅延ロードを実装するために使用することができます。

プロパティは、値を取得または設定することが意味するものをすべてカプセル化することによって、ある程度の抽象化をサポートします。

ほとんど/すべての場合でプロパティを使用しますが、副作用を避けるようにしてください。

8
Brian Rasmussen

ここでの2番目の質問「プロパティの代わりにフィールドを使用する必要があるのはいつですか?」は、 この他の回答 およびkind これも で簡単に触れていますが、本当に詳細。

一般に、他のすべての答えは、優れたデザインに関するスポットオンです。フィールドを公開するよりもプロパティを公開することを好みます。あなたはおそらく定期的に「Wow、これをプロパティの代わりにフィールドにしたとしたらどれほど悪いことになるか想像してください」と気づかないでしょう、「非常にまれです」と言う状況は考えにくいことです。

しかし、フィールドがプロパティよりも優れている点が1つあり、それが「ref」/「out」パラメータとして使用できるという利点があります。次のシグネチャを持つメソッドがあるとします:

public void TransformPoint(ref double x, ref double y);

そして、このメソッドを使用して、次のように作成された配列を変換するとします。

System.Windows.Point[] points = new Point[1000000];
Initialize(points);

X および Y がプロパティであるため、これを行う最も速い方法は次のとおりです。

for (int i = 0; i < points.Length; i++)
{
    double x = points[i].X;
    double y = points[i].Y;
    TransformPoint(ref x, ref y);
    points[i].X = x;
    points[i].Y = y;
}

そして、それはかなり良いことになるでしょう!他の方法で証明できる測定値がない限り、悪臭を放つ理由はありません。しかし、これほど高速であることが技術的に保証されているわけではないと思います。

internal struct MyPoint
{
    internal double X;
    internal double Y;
}

// ...

MyPoint[] points = new MyPoint[1000000];
Initialize(points);

// ...

for (int i = 0; i < points.Length; i++)
{
    TransformPoint(ref points[i].X, ref points[i].Y);
}

測定 自分で行うと、フィールドのあるバージョンは、プロパティのあるバージョン(.NET 4.6、Windows 7、x64、リリースモード、デバッガーなし)の約61%の時間がかかります。 TransformPointメソッドがより高価になるほど、差は顕著になりません。これを自分で繰り返すには、最初の行をコメントアウトして実行し、コメントアウトしないで実行します。

上記のパフォーマンス上の利点がなくても、 Interlocked または Volatile を呼び出すときなど、refおよびoutパラメーターを使用できると便利な場合があります。メソッドのファミリー。 注:これが初めての場合、Volatileは基本的にvolatileキーワードで提供されるのと同じ動作を実現する方法です。そのため、volatileのように、その名前が示唆するように、すべてのスレッドセーフの問題を魔法のように解決するわけではありません。

私はあなたが「ああ、プロパティではなくフィールドを公開し始めるべきだ」と主張しているように思われることは絶対にありません。重要なのは、「ref」または「out」パラメーターを使用する呼び出しでこれらのメンバーを定期的に使用する必要がある場合、特にプロパティの付加価値要素を必要としない単純な値型である可能性がある場合、引数を作成できます。

6
Joe Amenta

プライベート変数(フィールド)を他のクラスから自分のクラスのオブジェクトにアクセスできるようにしたい場合は、それらの変数のプロパティを作成する必要があります。

例えば、私が "id"と "name"という名前の変数を持っていて、それが非公開ですが、この変数がクラス外の読み書き操作に必要な状況があるかもしれません。そのような状況では、propertyはそのプロパティに定義されたget/setに応じてその変数を読み書きできるように手助けすることができます。プロパティはreadonly/writeonly/readwriteの両方にすることができます。

これがデモです

class Employee
{
    // Private Fields for Employee
    private int id;
    private string name;

    //Property for id variable/field
    public int EmployeeId
    {
       get
       {
          return id;
       }
       set
       {
          id = value;
       }
    }

    //Property for name variable/field
    public string EmployeeName
    {
       get
       {
          return name;
       }
       set
       {
          name = value;
       }
   }
}

class MyMain
{
    public static void Main(string [] args)
    {
       Employee aEmployee = new Employee();
       aEmployee.EmployeeId = 101;
       aEmployee.EmployeeName = "Sundaran S";
    }
}
5
Petryanu

MSDNのこのページには、次の場合に使用する比較とヒントがあります。

https://msdn.Microsoft.com/ja-jp/library/9d65as2e(v=vs.90).aspx

2
shivesh suman

技術的には、違いはないと思います。プロパティはユーザーによって作成されたフィールドまたはコンパイラによって自動的に作成されたフィールドのラッパーに過ぎません。フィールドをパブリックとして宣言することは単なる悪い習慣ですが、問題はありません。

2

もしあなたがスレッドプリミティブを使うつもりならあなたはフィールドを使わざるをえません。プロパティはあなたのスレッドコードを壊すことができます。それとは別に、コリーが言ったことは正しいです。

(これは本当にコメントになるはずですが、私はコメントを投稿することはできませんので、投稿として適切でない場合は申し訳ありません)。

以下のように、同等のプロパティdefが単にフィールドにアクセスしている場合に、プロパティの代わりにパブリックフィールドを使用することをお勧めします。

get { return _afield; }
set { _afield = value; }

彼らの推論は、公共の場は必要に応じて将来的には不動産に変えることができるということでした。当時私には少し奇妙に思えました。これらの投稿から判断すると、ここでも多くの人が同意しないと思われます。あなたは物事を変えようとしたのに何を言ったでしょうか?

編集:私は、この場所のすべてのコードベースが同時にコンパイルされたことを付け加えなければならないので、クラスのパブリックインタフェースを変更すること(パブリックフィールドをプロパティに変更すること)は問題ではないと考えていました。

2
Moe Sisko

基本的および一般的な違いは次のとおりです。

フィールド

  • 常に getおよびsetアクセスの両方を与える
  • CAN NOT副作用(例外のスロー、メソッドの呼び出し、取得/設定されているフィールド以外のフィールドの変更など)を引き起こす

物性

  • 常にではない getとsetの両方のアクセス権を与える
  • CAN副作用を引き起こす
2
Ted Mucuzany

フィールドは 通常のメンバ変数 またはクラスのメンバインスタンスです。プロパティは、それらの値を取得および設定するための 抽象化です 。プロパティは、クラス内のフィールドをプライベートとして公開した場合にフィールドを変更および取得する方法を提供するため、アクセサとも呼ばれます。一般に、メンバー変数をプライベートに宣言してから、それらのプロパティを宣言または定義する必要があります。

  class SomeClass
  {
     int numbera; //Field

     //Property 
    public static int numbera { get; set;}

  }
2
Vasim Shaikh

また、プロパティを使用すると、値を設定するときにロジックを使用できます。

そのため、値がxより大きい場合にのみ整数フィールドに値を設定したいと言うことができます。それ以外の場合は例外をスローします。

本当に便利な機能です。

2
GurdeepS

私のフィールドのデザインは、フィールドはその親、つまりクラスによってのみ修正される必要があるということです。結果変数が非公開になり、それから外部のクラス/メソッドを読む権利を与えることができるようにするためにGetだけでプロパティのシステムを通過します。その後、フィールドはプロパティによって取得され、読み取り専用になります。あなたがそれを修正したいなら、あなたはメソッド(例えば、コンストラクタ)を通過しなければならない、そして私はあなたを安全にするこの方法のおかげで私たちが「フランジする」ので私たちのコードをよりよく制御することを見つけます。可能な限りすべてのケース、変数/メソッド/クラスなどの概念など、常にすべてを公開することができます。私の考えでは、コードの開発、保守の単なる補助にすぎません。たとえば、ある人がパブリックフィールドを使用してコードを再開した場合、その人は目的、つまりコードが作成された理由の論理に関して「非論理的」なことを何でも行うことができます。それが私の見解です。

私が10個のプライベートフィールドのために私が10個のパブリックプロパティを書くべきである私が古典的なモデルプライベートフィールド/パブリックreadonlyプロパティを使うとき!コードは本当に速くなる可能性があります。私はプライベートセッターを発見し、今私はプライベートセッターでパブリックプロパティを使用しています。セッターはバックグラウンドでプライベートフィールドを作成します。

だから私の古い古典的なプログラミングスタイルは:

public class MyClass
{
 private int _id;
 public int ID { get { return _id; } }
 public MyClass(int id)
 {
  _id = id;
 }
}

私の新しいプログラミングスタイル:

public class MyClass
{
 public int ID { get; private set; }
 public MyClass(int id)
 {
  ID = id;
 }
}
2
Tony Pinot

伝統的にプライベートフィールドはgetterとsetterメソッドを通して設定されます。コードを少なくするために、代わりにプロパティを使用してフィールドを設定できます。

1
Chris Paine

フィールドとプロパティは互いに似ているように見えますが、2つの完全に異なる言語要素です。

  1. フィールドは、クラスレベルでデータを保存する唯一のメカニズムです。フィールドは、概念的にはクラススコープの変数です。クラス(オブジェクト)のインスタンスにデータを保存する場合は、フィールドを使用する必要があります。他に選択肢はありません。プロパティはデータを保存できませんが、保存できるように見える場合があります。下記をご覧ください。

  2. 一方でプロパティはデータを保存しません。これらはフィールドと同様の方法で構文的に呼び出すことができるメソッドのペア(getおよびset)であり、ほとんどの場合、アクセス(読み取りまたは書き込み用) )フィールド、これはいくつかの混乱の原因です。ただし、プロパティメソッドは(固定プロトタイプなどのいくつかの制限がある)通常のC#メソッドであるため、通常のメソッドが実行できることは何でも実行できます。つまり、1000行のコードを持ち、例外をスローしたり、別のメソッドを呼び出したり、仮想、抽象、またはオーバーライドすることができます。プロパティを特別なものにしているのは、C#コンパイラが特定のプロパティの検索に使用できるアセンブリに追加のメタデータを格納しているという事実です-広く使用されている機能です。

プロパティの取得および設定メソッドには、次のプロトタイプがあります。

PROPERTY_TYPE get();

void set(PROPERTY_TYPE value);

したがって、フィールドと2つの対応するメソッドを定義することにより、プロパティを「エミュレート」できることを意味します。

class PropertyEmulation
{
    private string MSomeValue;

    public string GetSomeValue()
    {
        return(MSomeValue);
    }

    public void SetSomeValue(string value)
    {
        MSomeValue=value;
    }
}

このようなプロパティエミュレーションは、標準のC++など、プロパティをサポートしないプログラミング言語で一般的です。 C#では、フィールドにアクセスする方法として常にプロパティを優先する必要があります。

フィールドのみがデータを保存できるため、より多くのフィールドクラスが含まれ、そのようなクラスのより多くのメモリオブジェクトが消費することを意味します。一方、クラスに新しいプロパティを追加しても、そのようなクラスのオブジェクトは大きくなりません。以下に例を示します。

class OneHundredFields
{
        public int Field1;
        public int Field2;
        ...
        public int Field100;
}

OneHundredFields Instance=new OneHundredFields() // Variable 'Instance' consumes 100*sizeof(int) bytes of memory.

class OneHundredProperties
{
    public int Property1
    {
        get
        {
            return(1000);
        }
        set
        {
            // Empty.
        }
    }

    public int Property2
    {
        get
        {
            return(1000);
        }
        set
        {
            // Empty.
        }
    }

    ...

    public int Property100
    {
        get
        {
            return(1000);
        }
        set
        {
            // Empty.
        }
    }
}

OneHundredProperties Instance=new OneHundredProperties() // !!!!! Variable 'Instance' consumes 0 bytes of memory. (In fact a some bytes are consumed becasue every object contais some auxiliarity data, but size doesn't depend on number of properties).

プロパティメソッドは何でもできますが、ほとんどの場合、オブジェクトのフィールドにアクセスする方法として機能します。他のクラスからフィールドにアクセスできるようにする場合は、2つの方法で実行できます。

  1. フィールドを公開する-推奨されません。
  2. プロパティを使用します。

以下は、パブリックフィールドを使用するクラスです。

class Name
{
    public string FullName;
    public int YearOfBirth;
    public int Age;
}

Name name=new Name();

name.FullName="Tim Anderson";
name.YearOfBirth=1979;
name.Age=40;

コードは完全に有効ですが、設計の観点からは、いくつかの欠点があります。フィールドは読み取りと書き込みの両方が可能なため、ユーザーがフィールドに書き込みできないようにすることはできません。 readonlyキーワードを適用できますが、この方法では、コンストラクターでのみ読み取り専用フィールドを初期化する必要があります。さらに、無効な値をフィールドに格納することを妨げるものは何もありません。

name.FullName=null;
name.YearOfBirth=2200;
name.Age=-140;

コードは有効です。すべての割り当ては非論理的ですが、実行されます。 Ageには負の値があり、YearOfBirthはかなり先であり、Ageに対応せず、FullNameはnullです。フィールドを使用すると、class Nameのユーザーがそのような間違いをするのを防ぐことはできません。

これらの問題を修正するプロパティを含むコードを次に示します。

class Name
{
    private string MFullName="";
    private int MYearOfBirth;

    public string FullName
    {
        get
        {
            return(MFullName);
        }
        set
        {
            if (value==null)
            {
                throw(new InvalidOperationException("Error !"));
            }

            MFullName=value;
        }
    }

    public int YearOfBirth
    {
        get
        {
            return(MYearOfBirth);
        }
        set
        {
            if (MYearOfBirth<1900 || MYearOfBirth>DateTime.Now.Year)
            {
                throw(new InvalidOperationException("Error !"));
            }

            MYearOfBirth=value;
        }
    }

    public int Age
    {
        get
        {
            return(DateTime.Now.Year-MYearOfBirth);
        }
    }

    public string FullNameInUppercase
    {
        get
        {
            return(MFullName.ToUpper());
        }
    }
}

クラスの更新バージョンには、次の利点があります。

  1. FullNameおよびYearOfBirthは、無効な値についてチェックされます。
  2. Ageは書き込み不可です。 YearOfBirthと現在の年から計算されます。
  3. 新しいプロパティFullNameInUppercaseは、FullNameを大文字に変換します。これは、ユーザーがより適切な形式でフィールド値を表示するために一般的に使用されるプロパティの使用例です。たとえば、DateTime形式の特定の数値で現在のロケールを使用します。

これに加えて、プロパティは、通常の.NETメソッドであるため、仮想またはオーバーライドとして定義できます。このようなプロパティメソッドには、通常のメソッドと同じルールが適用されます。

C#は、プロパティメソッドにインデックスパラメーターを持つプロパティであるインデクサーもサポートします。以下に例を示します。

class MyList
{
    private string[]                 MBuffer;

    public MyList()
    {
        MBuffer=new string[100];
    }

    public string this[int Index]
    {
        get
        {
            return(MBuffer[Index]);
        }
        set
        {
            MBuffer[Index]=value;
        }
    }
}

MyList   List=new MyList();

List[10]="ABC";
Console.WriteLine(List[10]);

C#3.0では自動プロパティを定義できるため以下に例を示します。

class AutoProps
{
    public int Value1
    {
        get;
        set;
    }

    public int Value2
    {
        get;
        set;
    }
}

class AutoPropsにはプロパティのみが含まれています(またはそのように見えます)が、2つの値を格納でき、このクラスのオブジェクトのサイズはsizeof(Value1)+sizeof(Value2) = 4 + 4 = 8バイトに等しくなります。

その理由は簡単です。自動プロパティを定義すると、C#コンパイラは、非表示フィールドと、この非表示フィールドにアクセスするプロパティメソッドを持つプロパティを含む自動コードを生成します。コンパイラが生成するコードは次のとおりです。

コンパイル済みアセンブリからILSpyによって生成されたコードを次に示します。クラスには、生成された非表示フィールドとプロパティが含まれます。

internal class AutoProps
{
    [CompilerGenerated]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private int <Value1>k__BackingField;

    [CompilerGenerated]
    [DebuggerBrowsable(DebuggerBrowsableState.Never)]
    private int <Value2>k__BackingField;

    public int Value1
    {
        [CompilerGenerated]
        get
        {
            return <Value1>k__BackingField;
        }
        [CompilerGenerated]
        set
        {
            <Value1>k__BackingField = value;
        }
    }

    public int Value2
    {
        [CompilerGenerated]
        get
        {
            return <Value2>k__BackingField;
        }
        [CompilerGenerated]
        set
        {
            <Value2>k__BackingField = value;
        }
    }
}

ご覧のとおり、コンパイラはフィールドを使用して値を保存します。フィールドはオブジェクトに値を保存する唯一の方法であるためです。

ご覧のとおり、プロパティとフィールドの使用構文は似ていますが、概念はまったく異なります。自動プロパティまたはイベントを使用する場合でも、非表示フィールドは実際のデータが保存されているコンパイラによって生成されます。

フィールド値を外部からアクセスできるようにする必要がある場合(クラスのユーザー)は、パブリックフィールドまたは保護フィールドを使用しないでください。フィールドは常にプライベートとしてマークする必要があります。プロパティを使用すると、値のチェック、書式設定、変換などを行うことができ、通常、将来の変更に対してコードをより安全で読みやすく、拡張しやすくします。

1
Timmy_A

ウィキペディアより - オブジェクト指向プログラミング

オブジェクト指向プログラミング(OOP)は、「オブジェクト」の概念に基づくプログラミングパラダイムです。これは、dataという形式のフィールドの形をとるデータ、およびコード、手続きの形式、しばしばmethods(強調が追加された)

プロパティは、実際にはオブジェクトの動作の一部ですが、オブジェクトの消費者にオブジェクトのデータを操作することの錯覚/抽象化を与えるように設計されています。

1
Zev Spitz

プロパティはフィールドをカプセル化するため、設定または取得する値に対して追加の処理を実行できます。フィールド値に対して前後処理を行わない場合は、通常、プロパティを使用するのはやり過ぎです。

1
Erik Burger

考えてみましょう。この部屋に入るための部屋とドアがあります。あなたがどのように入ってきているかを確認し、あなたの部屋を固定したいのであれば、そうでなければあなたはプロパティを使用する必要があります。

class Room {
   public string sectionOne;
   public string sectionTwo;
}

Room r = new Room();
r.sectionOne = "enter";

人々はsectionOneに入っていますかなり簡単に、何のチェックもありませんでした

class Room 
{
   private string sectionOne;
   private string sectionTwo;

   public string SectionOne 
   {
      get 
      {
        return sectionOne; 
      }
      set 
      { 
        sectionOne = Check(value); 
      }
   }
}

Room r = new Room();
r.SectionOne = "enter";

今、あなたはその人を調べて、彼が彼と何か悪を持っているかどうかについて知っています

1
user8080469

あなたが「車」であるクラスを持っているとき。プロパティは色、形です。

ここで、フィールドはクラスの範囲内で定義された変数です。

1
user406580

ほとんどの場合、変数名ではなく、ユーザーがアクセスするプロパティ名になります( field )。その理由は、.NETおよびC#ではすべてのユーザーを保護するためのベストプラクティスだと考えられているためです。クラスに関連付けられているため、インスタンス変数でも静的変数(クラス変数)でも、クラス内のデータの一部。

これらの変数すべてを、 setおよびget アクセサ を定義し、それらのデータを操作するときの検証などを可能にする対応するプロパティで保護します。

しかし、 Mathクラス (システム名前空間)のような他のケースでは、クラスに組み込まれている2、3の静的プロパティがあります。そのうちの1つは数学定数 _ pi _ です。

例えば。数学PI

また、PIは明確に定義されたデータであるため、PIを複数コピーする必要はなく、常に同じ値になります。そのため、静的変数はクラスのオブジェクト間でデータを共有するために使用されることがありますが、データのコピーを1つだけ必要とする場合には、通常は定数情報にも使用されます。

1
Nermien Barakat

フィールドはクラス内の変数です。フィールドは、アクセス修飾子を使用してカプセル化できるデータです。

プロパティは、状態とオブジェクトに関連付けられたデータを定義するという点でフィールドと似ています。

フィールドとは異なり、プロパティは人がデータを読み、データを書き込む方法を制御する特別な構文を持っています。これらはgetおよびset演算子として知られています。設定ロジックは、検証を行うためによく使用されます。

1
Neil Meyer

プロパティはフィールドを公開するために使用されます。プライベートフィールドの値の読み取り、書き込み、または操作を可能にするアクセサ(set、get)を使用します。

プロパティは格納場所を指定しません。代わりに、それらは自分の値を読み書きしたり計算したりするアクセサを持っています。

プロパティを使用して、フィールドに設定されているデータの種類に検証を設定できます。

例えば、年齢は負になることはできないので、正の値を許可する必要があるというプライベート整数フィールドageがあります。

ゲッターとセッターを使う方法とプロパティを使う方法があります。

 Using Getter and Setter

    // field
    private int _age;

    // setter
    public void set(int age){
      if (age <=0)
       throw new Exception();

      this._age = age;
    }

    // getter
    public int get (){
      return this._age;
    }

 Now using property we can do the same thing. In the value is a key Word

    private int _age;

    public int Age{
    get{
        return this._age;
    }

    set{
       if (value <= 0)
         throw new Exception()
       }
    }

自動実装プロパティgetおよびsetアクセサのロジックがない場合は、自動実装プロパティを使用できます。

U se自動実装プロパティcompilesがプライベートで匿名のフィールド を作成するとき、これはgetおよびsetアクセサを通してのみアクセスできます。

public int Age{get;set;}

抽象プロパティ 抽象クラスは抽象プロパティを持つことができ、それは派生クラスで実装されるべきです

public abstract class Person
   {
      public abstract string Name
      {
         get;
         set;
      }
      public abstract int Age
      {
         get;
         set;
      }
   }

// overriden something like this
// Declare a Name property of type string:
  public override string Name
  {
     get
     {
        return name;
     }
     set
     {
        name = value;
     }
  }

私たちは個人的にプロパティを設定することができますこれで私たちは個人的にautoプロパティを設定することができます(クラス内で設定します)

public int MyProperty
{
    get; private set;
}

このコードでも同じことができます。このプロパティでは、フィールドに値を直接設定する必要があるため、設定機能は使用できません。

private int myProperty;
public int MyProperty
{
    get { return myProperty; }
}
1

IMOのPropertiesは、以前に使用した "SetXXX()"と "GetXXX()"の関数/メソッド/インターフェイスの組み合わせですが、より簡潔でエレガントです。

1
Junchao Xu

プロパティは特別な種類のクラスメンバです。プロパティでは事前定義されたSetまたはGetメソッドを使用します。これらを使用して、プライベートフィールドの値の読み取り、書き込み、または変更を行うことができます。

たとえば、name、age、Employee_Idのプライベートフィールドを持つEmployeeという名前のクラスを考えてみましょう。クラスの外からこれらのフィールドにアクセスすることはできませんが、プロパティを介してこれらのプライベートフィールドにアクセスできます。

なぜ私たちはプロパティを使うのですか?

割り当てられて返されるものを制御できないため、クラスフィールドを公開して公開することは危険です。

例を使ってこれを明確に理解するには、PassMarkという名前のIDを持つ学生クラスを考えてみましょう。さて、この例ではパブリックフィールドに関するいくつかの問題

  • IDは-veにしないでください。
  • 名前をnullに設定できません
  • 合格マークは読み取り専用にしてください。
  • 学生の名前がない場合は、名前を返さないでください。

この問題を解決するにはGetとsetメソッドを使います。

// A simple example
public class student
{
    public int ID;
    public int PassMark;
    public string name;
}

public class Program
{
    public static void Main(string[] args)
    {
       student s1 = new student();
       s1.ID = -101; // here ID can't be -ve
       s1.Name = null ; // here Name can't be null
    }
}

それでは、getメソッドとsetメソッドの例を見てみましょう。

public class student
{
    private int _ID;
    private int _PassMark;
    private string_name ;
    // for id property
    public void SetID(int ID)
    {
        if(ID<=0)
        {
            throw new exception("student ID should be greater then 0");
        }
        this._ID = ID;
    }
    public int getID()
    {
        return_ID;
    }
}
public class programme
{
    public static void main()
    {
        student s1 = new student ();
        s1.SetID(101);
    }
    // Like this we also can use for Name property
    public void SetName(string Name)
    {
        if(string.IsNullOrEmpty(Name))
        {
            throw new exeception("name can not be null");
        }
        this._Name = Name;
    }
    public string GetName()
    {
        if( string.IsNullOrEmpty(This.Name))
        {
            return "No Name";
        }
        else
        {
            return this._name;
        }
    }
        // Like this we also can use for PassMark property
    public int Getpassmark()
    {
        return this._PassMark;
    }
}
1
ahmed alkhatib

追加情報:デフォルトでは、getおよびsetアクセサはプロパティ自体と同じくらいアクセス可能です。より制限的なアクセス修飾子を適用することで、アクセサのアクセシビリティを個別に(getおよびsetに対して)制御/制限できます。

例:

public string Name
{
    get
    {
        return name;
    }
    protected set
    {
        name = value;
    }
}

ここではgetはまだパブリックにアクセスされていますが(プロパティはパブリックなので)、setは保護されています(より制限されたアクセス指定子)。

0
Django