web-dev-qa-db-ja.com

ゲッター、セッター、およびプロパティのベストプラクティス。 Java vs. C#

私は今、C#クラスを受講しており、物事を行う最善の方法を見つけようとしています。私はJava背景から来ているので、Javaベストプラクティス;私はC#初心者です!

Javaプライベートプロパティがある場合、これを行います。

private String name;

public void setName(String name) {
   this.name = name;
}

public String getName() {
   return this.name;
}

C#では、これを行う方法はたくさんあることがわかります。

Javaのようにできます。

private string name;

public void setName(string name) {
   this.name = name;
}

public string getName() {
   return this.name;
}

または、この方法で行うことができます:

private string name;

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

または:

public string Name { get; set; }

どちらを使用する必要があり、各アプローチに関連する警告または微妙な点は何ですか?クラスを作成するとき、私はJava(特にEffective Javaを読む)から知っている一般的なベストプラクティスに従います。たとえば、不変性を優先しています(必要な場合にのみセッターを提供します)。これらのプラクティスがC#でセッターとゲッターを提供するさまざまな方法にどのように適合するかを知りたいだけです;基本的に、ベストプラクティスをJava worldからC#に変換するにはどうすればよいですか?

[〜#〜] edit [〜#〜]

Jon Skeetの答えへのコメントとしてこれを投稿していましたが、その後長くなりました。

重要なプロパティ(つまり、おそらく重要な処理と検証を伴う)についてはどうですか? getsetにカプセル化されたロジックを使用して、パブリックプロパティ経由で公開することはできますか?専用のセッターメソッドとゲッターメソッド(関連する処理ロジックと検証ロジック)を使用してこれを行う/行う必要がある理由.

88
Vivin Paliath

Pre-C#6

ささいな財産のために、私はこれらの最後を使います。ゲッターとセッターの両方がパブリックなので、これをpublicプロパティと呼ぶことに注意してください。

自動的に実装されるプロパティでは不変性は少し苦痛です-ゲッターのみを持つ自動プロパティを書くことはできません。一番近いのは:

_public string Foo { get; private set; }
_

これはreally不変ではありません...クラスの外では不変です。そのため、代わりにreal読み取り専用プロパティを使用することもできます。

_private readonly string foo;
public string Foo { get { return foo; } }
_

間違いなくgetName()setName()を書きたくないでしょう。 someの場合、特に高価な可能性があり、それを強調したい場合は、プロパティを使用するのではなく、Get/Setメソッドを記述するのが理にかなっています。ただし、メソッドについてはPascalCaseの.NET命名規則に従う必要があり、通常のメソッドではこのような些細なプロパティを実装したくないでしょう。

C#6

やっと、ついに適切な読み取り専用の自動実装プロパティができました:

_// This can only be assigned to within the constructor
public string Foo { get; }
_

同様に、doが何らかの作業を行う必要がある読み取り専用プロパティの場合は、メンバー本体プロパティを使用できます。

_public double Area => height * width;
_
84
Jon Skeet

必要なのがデータを保存する変数だけである場合:

_public string Name { get; set; }
_

読み取り専用に見せたいですか?

_public string Name { get; private set; }
_

またはさらに良い...

_private readonly string _name;

...

public string Name { get { return _name; } }
_

プロパティを割り当てる前に値のチェックを行いたいですか?

_public string Name 
{
   get { return m_name; }
   set
   {
      if (value == null)
         throw new ArgumentNullException("value");

      m_name = value;
   }
}
_

一般に、GetXyz()とSetXyz()は特定の場合にのみ使用され、適切だと感じたら直感的に使用する必要があります。一般に、ほとんどのget/setプロパティには多くのロジックが含まれておらず、予期しない副作用があったとしても非常に少ないと考えられます。プロパティ値を読み取るには、要求しているオブジェクトを作成するためにサービスを呼び出すか、ユーザーから入力を取得する必要がある場合、メソッドにラップし、BuildXyz()のようなものを呼び出しますGetXyz()より。

17
jeremyalan

メソッドを取得/設定するのではなく、C#でプロパティを使用します。彼らはあなたの便宜のためにそこにあり、それは慣用的です。

2つのC#の例では、1つはもう1つの構文糖衣です。インスタンス変数の単純なラッパーだけが必要な場合はautoプロパティを使用し、ゲッターやセッターにロジックを追加する必要がある場合はフルバージョンを使用します。

12
Ed S.

C#では、getおよび/またはsetのプライベートフィールドを公開するためのプロパティを優先します。あなたが言及するこのフォームは、getおよびsetが非表示のピボットバッキングフィールドを自動的に生成する自動プロパティです。

可能な場合は自動プロパティを優先しますが、C#でset/getメソッドペアを実行しないでください。

5
public string Name { get; set; }

これは単純に 自動実装プロパティ であり、技術的には通常のプロパティと同じです。コンパイル時にバッキングフィールドが作成されます。

最終的にすべてのプロパティは関数に変換されるため、最終的にコンパイルされる実際の実装は、Javaで使用されるものと同じです。

バッキングフィールドで特定の操作を行う必要がない場合は、自動実装プロパティを使用します。それ以外の場合は、通常のプロパティを使用します。操作に副作用がある場合や計算コストが高い場合は、get関数とset関数を使用し、そうでない場合はプロパティを使用します。

5
Steven Jeuris

最初に、あなたが書いたことを説明してみましょう。

// private member -- not a property
private string name;

/// public method -- not a property
public void setName(string name) {
   this.name = name;
}

/// public method -- not a property
public string getName() {
   return this.name;
}

// yes it is property structure before .Net 3.0
private string name;
public string Name {
   get { return name; }
   set { name = value; }
}

この構造は現在も使用されていますが、いくつかの追加機能を実行する場合に最適です。たとえば、値が設定されている場合は、解析してそれを大文字化し、内部使用を変更するためにプライベートメンバーに保存できます。

.net framework 3.0を使用

// this style is introduced, which is more common, and suppose to be best
public string Name { get; set; }

//You can more customize it
public string Name
{
    get;
    private set;    // means value could be set internally, and accessed through out
}

C#での幸運を祈ります

5
Waqas Raja

C#でどの方法を選択しても、最終結果は同じです。個別のgetterメソッドとsetterメソッドを使用してbackinng変数を取得します。プロパティを使用すると、ベストプラクティスに従っているため、どの程度冗長にするかが問題になります。

個人的には、自動プロパティ、最後のバージョンを選択します:public string Name { get; set; }、それらが最も少ないスペースを占有するため。検証などを追加する必要がある場合は、将来これらをいつでも拡張できます。

4
Paul Sasik

可能な限り、パブリックstring Name { get; set; }簡潔で読みやすいため。ただし、これが必要な場合があります

private string name;

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

C#では、getX()およびsetX()メソッドよりもプロパティを使用する方が望ましい方法です。また、C#ではプロパティにgetとsetの両方が必要ではないことに注意してください。get-onlyプロパティとset-onlyプロパティを使用できます。

public boolean MyProperty
{
    get { return something; }
}

public boolean MyProperty
{
    set { this.something = value; }
}
4
Zach Johnson

前述のように、これらのアプローチはすべて同じ結果になります。最も重要なことは、コンベンションを選んでそれに従うことです。最後の2つのプロパティの例を使用することを好みます。

3
jlafay

ここでのほとんどの回答と同様に、自動プロパティを使用します。直感的で少ないコード行で、よりクリーンです。クラスをシリアル化する必要がある場合は、[Serializable]属性でクラス[DataConract] /をマークします。 [DataContract]を使用している場合は、メンバーに

[DataMember(Name="aMoreFriendlyName")]
public string Name { get; set; }

プライベートセッターまたはパブリックセッターは、好みによって異なります。

また、自動プロパティにはゲッターとセッター(パブリックまたはプライベート)の両方が必要であることに注意してください。

/*this is invalid*/
public string Name 
{ 
    get; 
   /* setter omitted to prove the point*/
}

または、get/setのみが必要な場合は、バッキングフィールドを自分で作成します

2
ram

どちらを使用する必要があり、各アプローチに関連する警告または微妙な点は何ですか?

プロパティを使用する場合、まだ言及されていない注意事項が1つあります。プロパティでは、ゲッターまたはセッターのパラメーター化を行うことはできません。

たとえば、リストアイテムを取得し、同時にフィルターも適用するとします。 getメソッドを使用すると、次のように記述できます。

_obj.getItems(filter);
_

対照的に、プロパティを使用すると、最初にすべてのアイテムを返す必要があります

_obj.items
_

次のステップでフィルターを適用するか、異なる条件でフィルターされたアイテムを公開する専用のプロパティを追加する必要があります。これにより、すぐにAPIが膨張します。

_obj.itemsFilteredByX
obj.itemsFilteredByY
_

迷惑になることがあるのは、プロパティで始めたときです。 _obj.items_その後、ゲッターまたはセッターのパラメーター化が必要であるか、クラスAPIユーザーにとって物事が簡単になることを後で発見しました。 APIを書き換えて、このプロパティにアクセスするコード内のすべての場所を変更するか、代替ソリューションを見つける必要があります。対照的に、getメソッドでは、たとえばobj.getItems()、単にメソッドのシグネチャを拡張して、オプションの「設定」オブジェクトを受け入れることができます。 obj.getItems(options)は、メソッドを呼び出すすべての場所を書き換える必要がありません。

そうは言っても、C#の(自動実装)プロパティは、ほとんどの場合、パラメーター化は必要ない可能性があるため、ここで説明するさまざまな理由から、非常に便利なショートカットです。

0
B12Toaster