C#3.0自動プロパティ—有用かどうか?[閉まっている]


155

注:これは、C#を使い始めたときに投稿されました。2014年の知識があれば、自動プロパティはC#言語でこれまでに起こった中で最高のものの1つであると本当に言えます。

プライベートフィールドとパブリックフィールドを使用して、C#でプロパティを作成するのに慣れています。

private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

今、.NET 3.0では、自動プロパティを取得しました。

public string Title { get; set; }

私はこれが哲学的/主観的な質問であることを知っていますが、各フィールドに5行のコードを保存する以外に、これらの自動プロパティを使用する理由はありますか?私の個人的な不満は、これらのプロパティが私から何かを隠していることであり、私は黒魔術の大ファンではありません。

実際、非表示のプライベートフィールドはデバッガにも表示されません。これは、get / set関数が何も実行しないという事実を考えると問題ありません。しかし、実際にゲッター/セッターロジックを実装する場合は、とにかくプライベート/パブリックペアを使用する必要があります。

後でゲッター/セッターのロジックを変更する機能を失うことなく、多くのコード(1行と6行)を保存できるというメリットがありますが、パブリックフィールド "Public string Title"を宣言せずに、すでにそれを行うことができます。 {getの必要性; セットする; }ブロックし、さらに多くのコードを保存します。

それで、ここで何が欠けていますか?なぜ誰もが実際に自動プロパティを使用したいのですか?


86
「私の個人的な不満は、これらのプロパティが私から物を隠していることであり、私は黒魔術の大ファンではありません。」えっ?あなたはコンパイラが常にあなたからトンを隠していることを知っていますよね?アセンブリ(より正確には、コードの実際の1と0)を記述しているのでない限り、記述したすべてのものは、何かを隠しています。
Charles Boyung、

回答:



62

はい、コードを保存するだけです。大量にあると読みやすくなります。記述が速く、保守も簡単です。コードを保存することは常に良い目標です。

さまざまなスコープを設定できます。

public string PropertyName { get; private set; }

そのため、プロパティはクラス内でのみ変更できます。リフレクションを介してプライベートセッターにアクセスできるため、これは実際には不変ではありません。

C#6以降では、真のreadonlyプロパティ、つまりコンストラクターの外では変更できない不変のプロパティを作成することもできます。

public string PropertyName { get; }

public MyClass() { this.PropertyName = "whatever"; }

コンパイル時に次のようになります。

readonly string pName;
public string PropertyName { get { return this.pName; } }

public MyClass() { this.pName = "whatever"; }

多くのメンバーを持つ不変クラスでは、これにより余分なコードが大幅に節約されます。


「そのため、機能を失うことはありません。」それらをどのようにデバッグしますか?
WAL

2
@wal-デバッグするものは何ですか?その観点からは、基本的にメンバー変数を扱っています。
キース

6
@wal-メンバー変数にアクセスできるのと同じように、ブレークポイントをそれらに置くことができ、それらにステップインすることはできません。しかし、なぜあなたはそうしたいのですか?自動プロパティが実際に行うことは、些細なことと自動生成の両方です。もしバグが非常にありそうにない1つの場所にいる場合は。
キース

3
キースの外に持っていく必要があるかもしれません。:)
WAL

1
しかし、わかりました。myObj.Titleへのセッター呼び出しが多数あると想定します。値が「テキスト」からnullに変化する場所、つまり条件付きブレークポイントを確認したいとします。どのようにそれを達成しますか?セッターにブレークポイントを設定することもできません
ウォル

45

プロパティの代わりにフィールドを使用することの3つの大きな欠点は次のとおりです。

  1. フィールドにデータバインドすることはできませんが、プロパティにバインドすることはできます
  2. フィールドの使用を開始した場合、後で(簡単に)プロパティに変更することはできません
  3. フィールドに追加できないプロパティに追加できる属性がいくつかあります

7
「フィールドの使用を開始した場合、後で(簡単に)プロパティに変更することはできません。」
Homam

6
@Homam主に、フィールドでリフレクションを使用するコンシューマーコードは、FieldInfoの使用からPropertyInfoへの切り替えが必要になるため、機能しなくなります。
WCWedin

8
@Homamまた、フィールドをプロパティに変更すると、バイナリ互換性が失われ、フィールドのすべてのコンシューマに再コンパイルが必要になります。
Odrade、2011年

1
再コンパイルとリフレクションの問題は別として、Visual Studioを使用してフィールドをカプセル化するのは非常に簡単です。Ctrl-R+ Eを使用すると、適切なゲッター/セッターを使用してフィールドをプロパティに変換できます。(または、フィールドを右クリックして、リファクタリングし、フィールドをカプセル化します)。
JoeBrockhaus

@Hommamフィールドは左辺値(それらは変数です)で、プロパティはそうではありません。それがフィールドであったときにコンパイルされたかもしれないものは、それがプロパティであるときではないかもしれません。
マーク

29

私は個人的に自動プロパティが大好きです。コード行を保存することの何が問題になっていますか?ゲッターやセッターで何かをしたい場合は、後でそれらを通常のプロパティに変換しても問題はありません。

あなたが言ったように、あなたはフィールドを使うことができて、あなたが後でそれらにロジックを追加したいなら、あなたはそれらをプロパティに変換するでしょう。しかし、これはリフレクションの使用で問題を引き起こす可能性があります(そしておそらく他の場所で?)。

また、プロパティを使用すると、フィールドでは実行できないゲッターとセッターに異なるアクセスレベルを設定できます。

varキーワードと同じだと思います。個人的な好みの問題。


29

C ++の作成者であるBjarne Stroustrupから:

特に、get関数とset関数が多いクラスは嫌いです。多くの場合、それはそもそもクラスであってはならないことを示しています。これは単なるデータ構造です。そして、それが本当にデータ構造である場合、それをデータ構造にします。

そして、あなたは何を知っていますか?彼は正しい。単に「オブジェクト指向」であるため、実際にget / set内で何も行わずに、getおよびsetでプライベートフィールドを単にラップする頻度はどれくらいですか。これは問題に対するマイクロソフトのソリューションです。それらは基本的に、バインドできるパブリックフィールドです。


2
これはもっとポイントがあると思う。あまりにも多くの人々が、autoプロパティを、美化されたパブリックフィールドに過ぎない恐ろしくカプセル化された(またはまったくカプセル化されていない)クラスを書くための青信号として見ています。もちろん、これはツール自体ではなく、ツールの使用方法に関する問題ですが、プロパティについて一般的に説明する際に言及することが重要だと思います。
サラ2015

18

残念ながら、自動プロパティが不変オブジェクト(通常は不変構造体)に役立たないことは、誰も言及していないようです。そのため、あなたは本当にすべきです:

private readonly string title;
public string Title
{
    get { return this.title; }
}

(フィールドは渡されたパラメーターを介してコンストラクターで初期化され、その後読み取り専用になります。)

そのため、これには単純なget/ private set自動プロパティよりも利点があります。


構造体がある場合、そのプロパティを変更すると、新しい構造体になります。これは、内部的に不変の参照型が必要な場合にのみ問題になります。これが必要になる理由はわかりません。
キース

@キース:あなたの最初の文は実際には間違っているようです。
Domenic

3
public string Title { get; private set; }まったく同じ結果にならないでしょうか?もちろん、クラス内から変更することもできますが、変更すると他の問題が発生します...:p
Svish

2
@Svish -その使用は、我々はこれらの「別の問題」隠れていたことを意味するので、C#での読み取り専用キーワードを使用すべきではありません、その引数によって
ザイドMasud

2
外部APIの観点からは、それほど大きな違いはないということです。したがって、必要に応じて自動プロパティを使用できます。あなたが何かを行うことができれば最善のことは、当然だろうpublic string Title { get; private readonly set; }
Svish

12

インターフェース定義でプロパティを使用でき、インターフェース定義でパブリックフィールドを使用できないため、私は常にパブリックフィールドの代わりにプロパティを作成します。


8

自動プロパティは、C#の他のものと同じくらい黒魔術です。最初に通常のC#プロパティに展開するのではなく、ILにコンパイルするという点でそれについて考えると、他の多くの言語構成要素よりもずっと黒魔術が少なくなります。


5

私は常に自動プロパティを使用しています。C#3以前は、すべての入力に煩わされることはなく、代わりにパブリック変数を使用していました。

私が見落としているのは、これを実行できることだけです。

public string Name = "DefaultName";

プロパティを持つコンストラクタにデフォルトをシフトする必要があります。面倒:-(


4
:C#6からの自動プロパティの初期化子を使用すると、すぐにこれを行うことができるようになりますpublic string Name { get; set; } = "DefaultName"; blogs.msdn.com/b/csharpfaq/archive/2014/11/20/...
カルロス・ムニョス

5

直感的で、コードの行を削減する構成は、大きなプラスになると思います。

これらの種類の機能は、Rubyのような言語を非常に強力にするものです(それは、余分なコードの削減にも役立つ動的機能です)。

Rubyはこれをずっと持っていました:

attr_accessor :my_property
attr_reader :my_getter
attr_writer :my_setter

2

私が彼らに持っている唯一の問題は、彼らが十分に遠くに行かないことです。自動プロパティを追加したコンパイラの同じリリース、部分メソッドが追加されました。彼らが2つをまとめなかった理由は私を超えています。単純な "部分的なOn <PropertyName> Changed"があれば、これらのことは本当に便利になります。


複数の部分メソッドを別のメソッド内に置くことができます。それらのためにある種の自動パターンを作成することは混乱を招くでしょう。
マシューホワイト

2

それはシンプルで短く、プロパティの本体内のどこかに実際の実装を作成したい場合でも、型の外部インターフェイスを壊すことはありません。

それと同じくらい簡単です。


1

ここで注意すべき点の1つは、私の理解では、これはC#3.0側の単なる構文上の糖衣であり、コンパイラーによって生成されるILが同じであることを意味します。私は黒魔術を避けることに同意しますが、同じことに対して、同じように、少ない行は通常良いことです。


1

私の意見では、パブリックフィールドではなく、常に自動プロパティを使用する必要があります。とはいえ、ここに妥協点があります。

プロパティに使用する命名規則を使用して、内部フィールドから始めます。あなたが最初に

  • アセンブリの外部からフィールドにアクセスする必要がある、または
  • ゲッター/セッターにロジックをアタッチする必要がある

これを行う:

  1. フィールドの名前を変更する
  2. プライベートにする
  3. パブリックプロパティを追加する

クライアントコードを変更する必要はありません。

しかし、いつかはシステムが成長し、個別のアセンブリと複数のソリューションに分解することになります。それが起こると、公開されたフィールドはすべてあなたを悩ませるようになります。ジェフが述べたように、パブリックフィールドをパブリックプロパティに変更することは、APIの重大な変更だからです。


0

私はCodeRushを使用していますが、自動プロパティよりも高速です。

これをする:

 private string title;
public string Title
{
    get { return title;  }
    set { title = value;  }
}

合計8回のキーストロークが必要です。


5
CTRLとVを押したままにすると、/非常にすばやく/たくさんのものを貼り付けることができますが、それでも「良くなる」わけではありません。これは元の質問にどのように答えますか?
JBRウィルキンソン2010

0

コードスニペットを使用すると、同じ名前の自動プロパティは合計7つのキーストロークになります;)


0

@Domenic:わかりません..これを自動プロパティで行うことはできませんか?:

public string Title { get; }

または

public string Title { get; private set; }

これはあなたが言っていることですか?


可能ですが(後者;前者はコンパイルされません)、フィールドはオブジェクト内で不変ではありません。
Domenic

注意してください。読み取り専用のフラグが立てられている場合、構造体のみが不変であり、クラスは割り当て不可です。
Guvante 2008年

0

自動プロパティに関する私の最大の不満は、時間を節約するように設計されていることですが、後で完全なプロパティに拡張する必要があることがよくあります。

VS2008に欠けているのは、Explode Auto-Propertyリファクタリングです。

カプセル化フィールドリファクタリングがあるという事実により、パブリックフィールドを使用するだけで作業が速くなります。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.