プライベートプロパティを作成する必要がありますか?


19
private string mWhatever;

private string Whatever
{
    get
    {
        return this.mWhatever;
    }
    set
    {
        this.mWhatever = value;
    }
}

私は、個人であろうとなかろうと、すべてのメンバーのプロパティを作成する人々を見てきました...これは意味を成しますか?それを含むクラス内のメンバーへのアクセスを制御したい場合、1%のケースでそれが理にかなっていることがわかりました。すべてのメンバーのプロパティを使用しないと、矛盾が発生し、メンバーにはアクセス権があるかどうか(クラスのスコープ内で両方にアクセスできるため)。

回答:


17

簡単な答え:はい、必要がある場合。それ以外の場合は、自動実装プロパティのゲッターとセッターを使用しますprivate string Whatever { get; set;}

  • クローズドドメインアプローチを使用している場合、非常に便利です
  • 値を設定するときに特定のロジックをチェックする必要がある場合にも便利です

プライベートセッターを使用する場合の完全な説明は次のとおりです。C#プロパティの使用法


必要に応じて、後でプロパティを公開するのも簡単です。
トムピクルス14

4
クローズドドメインアプローチとは何ですか?
14

1
クラスのプロパティにあるプライベートセッターを参照していました。オブジェクトから値を設定するための直接アクセスを防ぎ、値を設定する前に何らかのロジックチェックを容易にする必要があります。
ELユスボフ

プライベートな変数をパブリックなセッター/ゲッター(単純な場合でも)にすると、コードをライブラリにコンパイルした場合、単純なセッター/ゲッターをサイド変数を持つものに置き換えても署名が変更されないという利点があります。効果などがありますが、代わりに単純なパブリック変数を使用する場合、プライベートなw / non naive setter / getterに変更すると、ライブラリシグネチャが変更されます。..これは、ライブラリがそのように変更された場合、ライブラリのコンシューマが再コンパイルする必要があることを意味します。
オリオンelenzil

12

ここでいくつかの良い答えが既にありますが、それらのほとんどはあなたの質問の一点を見逃していると思います:

私は、個人であろうとなかろうと、すべてのメンバーのプロパティを作成する人々を見てきました...これは意味を成しますか?

これは、すべてのメンバーに事前に必要になることはめったにないと思います。皮切りに

 private string Whatever;

後でこの特定のメンバーのカプセル化または条件付きブレークポイントが必要になった時点で、同じ名前のプロパティで置き換えることができます-ほとんどの場合、を使用するコードを変更することなくWhatever。ただし、注意が必要です。微妙な違いがあります。このSO投稿のブライアンラスムッセンの回答をご覧ください (リンクはEmmad Kareemからも提供されています、+ 1)。


+1、また、あなたは正しいです、ほとんどの回答は元の質問ポイントを逃しました、私たちは典型的なITの男です:)
NoChance

事後のプロパティへのフィールドのリファクタリングは悪夢です。すべてのコンシューマを再コンパイルする必要があります。カスタムプロパティを含むように自動プロパティを変更するのは簡単です。コードがリファクタリングする可能性がわずかでもある場合、最初からプロパティを使用するだけで作業が大幅に減ります。
ダン

@Dan:ほとんどのプロジェクトで努力はまったく同じであることがわかりました。どちらの場合も再コンパイルする必要があります。それにもかかわらず、プロパティ、特に自動プロパティを使用すると、「出力」パラメータでのメンバー変数のリフレクションまたは使用に関するいくつかの微妙な問題を回避するのに役立つことが正しいと思います。
ドックブラウン

@DocBrownいずれにしても、それは間違いなくキャッチオールステートメントではありません。単純にしてフィールドを使用するだけの理由はたくさんあります。ただし、リファクタリングを予測できる場合は、微妙な問題でさえも検討する価値があります。
ダン

7

このアプローチの最大の利点の1つは、変数いつ変更れるかを制御できることです。

以下を考慮してください。
大規模なプロジェクトをデバッグしています。特定のメソッドが例外をスローします。ブレークポイントを設定すると、特定のメンバー変数の値が間違っていることがわかります。あなたのコードがこの変数に非常に広範囲に依存しており、何百もの書き込みの使用法を見つけたとしましょう(スパゲッティのシナリオ)。したがって、これらの使用法のどれが悪い値を割り当てているのかわかりません。
コードがマルチスレッドである場合、デバッグは本当の悪夢になる可能性があります。

プロパティを使用すると、セッターにブレークポイントを設定できます。条件と組み合わせると、1回の実行で特定できます。

VC ++にはデータブレークポイントがありますが、アンマネージコードでのみ使用できます。


1

プロパティを使用しない場合、フィールドを使用して変数データを保存することが唯一のオプションです。プロパティとフィールドには大きな違いがあります。これらの違いのほとんどは、フィールドとプロパティにあります。違いを調べてから、アプリケーションのニーズに応じて選択することをお勧めします。ただし、プロパティの代わりにフィールドを使用することは、その性質と欠点のため、一般的なオブジェクト指向の慣行ではないことに留意してください。


1

プライベートプロパティは、クラスの内部にあるものの動作をカプセル化するのに非常に役立ちます。それらがプライベートだからといって、プロパティが提供する構文糖を利用してはいけないという意味ではありません。


ただし、この例は貧弱なものです。このような定型的なプロパティゲッターとセッターは、ほとんど常に悪い考えです。C#3.0以降を使用している場合、自動プロパティははるかに優れたアイデアです。

private string Whatever { get; set; };

これは短く、簡潔で、はるかに読みやすいです。実際、バッキング変数を宣言するよりもわずかに長いだけです。

最も重要なことは、プログラムの他の部分のセマンティクスを変更せずに、自動プロパティをいつでも完全なプロパティに変換できることです。したがって、検証またはエラー処理を追加する必要がある場合は、簡単に追加できます。


現状では、コンストラクターの値への書き込みのみを強制するために、読み取り専用のプロパティを持たないのは残念だと常に思っていました(不変の型好む)が、これはC#6.0で次のように追加されました。 「自動プロパティ初期化」により、次のことが可能になります。

private string Whatever { get; } = ...;

または

private string Whatever { get; };

に加えて

    Whatever = ...;

コンストラクター内。


0

プライベートプロパティに対してこれを行うことは絶対に必要ではありませんが、アクセス方法を変更することなく、プロパティが基になる値を取得/設定する方法を変更できます。

たとえば、基になる値の設定方法を変更する場合:

private string Whatever
{
    get
    {
        return this.mWhatever;
    }
    set
    {
        this.mWhatever = string.IsNullOrEmpty(value) ? string.Empty : value;
    }
}

0

うん

私は個人的にこれをキャッシングメカニズムとして使用しており、プロパティレベルキャッシングと呼ぶかもしれません。

private List<User> users;
private List<User> Users
{
    get
    {
        if(users == null) users = new UserManager().GetUsers();
        return users;
    }
}

クラス内の他の場所ではUsersusersフィールドではなくプロパティを使用しています。

別の実行可能な状況としては、フィールドに何らかのロジックを実装したい場合がありますが、クラスでは集中化された方法です。したがって、GetFoo()メソッドまたはフィールドのFooプロパティの両方を作成できfooます。

private string foo;
private string Foo
{
    get
    {
        return "Mr. " + foo;
    }
}

0

考慮すべき他の事項:

実際のプロパティは実装の詳細です。OOPの目標の1つは、実用的な実装の詳細の公開を最小限に抑えることです。

これは、プロパティを非表示にし、ゲッターとセッターを介してのみ公開する場合、はるかに制御しやすいためです。たとえば、ゲッターは入力を検証し、プロパティが無効な状態に設定されるのを防ぐことができます。値を変更する機能がタイムクリティカルである場合、セッターはこれに対しても保護できます。ゲッターは、何らかの理由で実際の値を取得するのに費用がかかるため、遅延初期化やキャッシュを実行できます。

ゲッターとセッターを公開し、プロパティを非表示にすると、プロパティがまったく必要ない場合があります。ゲッターは、呼び出し時に値を計算したり、タスクを他の場所に委任したり、仕様を満たすことができるものを委任したりできます。クラスで重要なのは、クラスからアクセスできる情報であり、その情報が内部的にどのように表されるかではありません。

もちろん、クラス外の何かがプロパティに直接アクセスできることに悪影響がない場合は、それを公開するだけです。しかし、私の経験では、そのようなケースは比較的少なく、はるかに近いです。


0

これは古い質問であり、@ Yusubovが言ったことはすべて正しいことを知っていますが、セッターの特定のロジックに関する彼の2番目の箇条書きに関しては、誰もこれについて特に言及していないので、完璧な例はあなたのクラスですINotifyPropertyChangedインターフェイスを実装します。

これは、以下のクラスのようにセッターのロジックを介して特定のプロパティがいつ変更されたかを知ることができるWCFおよびSilverlightでトン使用されます。

public class Settings : INotifyPropertyChanged
{
    public Settings() 
    { 
        this.CountryField = String.Empty; 
    }

    private string CountryField;
    public string Country
    {
        get { return this.CountryField; }
        set
        {
            if (Object.ReferenceEquals(this.CountryField, value)) { return; }

            this.CountryField = value;
            this.RaisePropertyChanged("Country");
        } 
    }

    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler propertyChanged = this.PropertyChanged;

        if (propertyChanged != null)
            propertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }
}
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.