297

C#プロパティ構造はプライベートアクセス修飾子と一緒に使用することもできることに気づきました。

private string Password { get; set; }

これは技術的には興味深いものですが、プライベートフィールドでは式典がさらに少なくなるため、いつ使用するかは想像できません。

private string _password;

また、内部で取得できる必要があるが、設定できない、または設定できないがプライベートフィールドを取得できない必要があるのはいつか想像できません。

private string Password { get; }

また

private string Password { set; }

しかし、ネストされた/継承されたクラスのユースケースや、プロパティの値を返すだけでなく、get / setにロジックが含まれる場合もありますが、プロパティを厳密に単純に保ち、明示的なメソッドにロジックを実行させる傾向がありますが、例:GetEncodedPassword()

誰かが何らかの理由でC#でプライベートプロパティを使用していますか、それとも技術的には可能ですが、実際にはほとんど使用されていないコード構造の1つにすぎませんか?

補遺

良い答え、それらを読んで、私は私有財産のこれらの使用法をカリングしました:

  • プライベートフィールドを遅延ロードする必要がある場合
  • プライベートフィールドに追加のロジックが必要な場合、または計算値である場合
  • プライベートフィールドはデバッグが難しい場合があるため
  • 「自分に契約を提示する」ために
  • シリアル化の一部として公開されたプロパティを内部的に変換/簡素化する
  • クラス内で使用されるグローバル変数のラッピング
4

19 に答える 19

247

値をキャッシュする必要があり、それを遅延ロードしたい場合に使用します。

private string _password;
private string Password
{
    get
    {
        if (_password == null)
        {
            _password = CallExpensiveOperation();
        }

        return _password;
    }
}
于 2010-07-22T15:05:41.757 に答える
161

他の人が言及しているように、私のコードでのこれの主な使用法は怠惰な初期化です。

フィールドよりもプライベートプロパティのもう1つの理由は、プライベートプロパティは、プライベートフィールドよりもはるかに簡単にデバッグできることです。「このフィールドが予期せず設定されています。このフィールドを設定する最初の呼び出し元は誰ですか?」などのことをよく知りたいです。セッターにブレークポイントを設定して[実行]をクリックするだけで、はるかに簡単になります。そこにログインできます。そこにパフォーマンスメトリックを配置できます。デバッグビルドで実行される整合性チェックを行うことができます。

基本的に、それは次のようになります。コードはデータよりもはるかに強力です。必要なコードを書くことができるテクニックはどれも良いものです。フィールドではコードを記述できませんが、プロパティでは記述できます。

于 2010-07-22T15:16:34.403 に答える
46

ネストされた/継承されたクラスのユースケースがあるか、プロパティの値を返すだけでなく、get/setにロジックが含まれている可能性があります。

プロパティのゲッターやセッターにロジックが必要ない場合でも、個人的にこれを使用します。プロパティを使用すると、プライベートプロパティであっても、必要に応じて後でロジックをゲッターに追加できるように、コードの将来性を保証するのに役立ちます。

プロパティが最終的に追加のロジックを必要とする可能性があると感じた場合は、フィールドを使用する代わりにプライベートプロパティにラップすることがあるので、後でコードを変更する必要はありません。


半ば関連するケース(あなたの質問とは異なりますが)では、私は公共の財産でプライベートセッターを非常に頻繁に使用します:

public string Password 
{
    get; 
    private set;
}

これにより、パブリックゲッターが提供されますが、セッターはプライベートに保たれます。

于 2010-07-22T14:56:05.130 に答える
26

プライベートgetonlyプロパティの1つの良い使用法は、計算値です。何度か私はプライベート読み取り専用のプロパティを持っていて、私のタイプの他のフィールドに対して計算を行うだけです。それはメソッドに値するものではなく、他のクラスにとっても面白くないので、私有財産です。

于 2010-07-22T15:06:12.847 に答える
21

怠惰な初期化は、それらがきちんとできる1つの場所です。

private Lazy<MyType> mytype = new Lazy<MyType>(/* expensive factory function */);

private MyType MyType { get { return this.mytype.Value; } }

// In C#6, you replace the last line with: private MyType MyType => myType.Value;

次に、次のように書くことができます。単一の場所で遅延インスタンス化されるという事実をカプセル化するのthis.MyTypeではなく、どこにでも。this.mytype.Value

残念なことに、C#は、バッキングフィールドをプロパティにスコープして(つまり、プロパティ定義内で宣言して)完全に非表示にし、プロパティを介してのみアクセスできるようにすることをサポートしていません。

于 2010-07-22T15:01:49.057 に答える
15

私が考えることができる唯一の使用法

private bool IsPasswordSet 
{ 
     get
     {
       return !String.IsNullOrEmpty(_password);
     }
}
于 2010-07-22T14:59:50.590 に答える
13

プロパティとフィールドは1対1ではありません。プロパティはクラスのインターフェースに関するものであり(パブリックインターフェースまたは内部インターフェースに関するものであるかどうかに関係なく)、フィールドはクラスの実装に関するものです。プロパティは、フィールドを公開する方法として見なされるべきではなく、クラスの意図と目的を公開する方法として見なされるべきです。

プロパティを使用してクラスを構成するものについて消費者に契約を提示するのと同じように、非常によく似た理由で自分自身に契約を提示することもできます。そうです、私はそれが理にかなっているときにプライベートプロパティを使用します。プライベートプロパティは、遅延読み込み、プロパティが実際にはいくつかのフィールドと側面の集合体であるという事実、またはプロパティを呼び出しごとに仮想的にインスタンス化する必要があるという事実など、実装の詳細を隠すことができる場合があります(think DateTime.Now)。クラスのバックエンドで自分自身にもこれを強制することが理にかなっている場合が確かにあります。

于 2010-07-22T15:01:45.283 に答える
9

私はそれらをシリアル化で使用します。DataContractSerializerまたはprotobuf-netのようなもので、この使用法をサポートします(サポートXmlSerializerしません)。シリアル化の一部としてオブジェクトを単純化する必要がある場合に役立ちます。

public SomeComplexType SomeProp { get;set;}
[DataMember(Order=1)]
private int SomePropProxy {
    get { return SomeProp.ToInt32(); }
    set { SomeProp = SomeComplexType.FromInt32(value); }
}
于 2010-07-22T15:29:10.000 に答える
6

私がいつもしていることの1つは、「グローバル」変数/キャッシュをに格納することですHttpContext.Current

private static string SomeValue{
  get{
    if(HttpContext.Current.Items["MyClass:SomeValue"]==null){
      HttpContext.Current.Items["MyClass:SomeValue"]="";
    }
    return HttpContext.Current.Items["MyClass:SomeValue"];
  }
  set{
    HttpContext.Current.Items["MyClass:SomeValue"]=value;
  }
}
于 2010-07-22T15:37:18.167 に答える
6

プライベートプロパティを使用して、頻繁に使用するサブプロパティにアクセスするためのコードを減らします。

    private double MonitorResolution
    {
        get { return this.Computer.Accesories.Monitor.Settings.Resolution; }
    }

サブプロパティが多い場合に便利です。

于 2014-12-03T10:25:23.057 に答える
5

私は時々それらを使用します。プロパティにブレークポイントを簡単に設定したり、ログステートメントなどを追加したりできる場合は、デバッグが容易になります。

後で何らかの方法でデータのタイプを変更する必要がある場合、またはリフレクションを使用する必要がある場合にも役立ちます。

于 2010-07-22T14:55:31.420 に答える
3

私はこの質問が非常に古いことを知っていますが、以下の情報は現在の回答のいずれにも含まれていませんでした。

いつ内部で取得できる必要があるのに設定できないのか想像できません

依存関係を注入する場合は、読み取り専用プロパティを示すため、セッターではなく、プロパティにゲッターを設定することをお勧めします。つまり、プロパティはコンストラクターでのみ設定でき、クラス内の他のコードで変更することはできません。

また、Visual Studio Professionalは、フィールドではなくプロパティに関する情報を提供するため、フィールドが使用されていることを簡単に確認できます。

PorpField

于 2019-04-03T12:14:54.777 に答える
2

プライベートメソッドであっても、get/setメソッドを使用してメンバーのみを変更するのが一般的な方法です。さて、これの背後にあるロジックは、get / setが常に特定の方法で動作することを知っているためです(たとえば、イベントの発生)。これは、プロパティスキームに含まれないため、意味がないようです...しかし、古い習慣は一生懸命に死にます。

于 2010-07-22T14:57:17.500 に答える
2

プロパティsetまたはget(遅延初期化を考えてください)に関連付けられたロジックがあり、プロパティがクラスのいくつかの場所で使用されている場合、これは完全に理にかなっています。

まっすぐなバッキングフィールドなら?正当な理由として何も思い浮かびません。

于 2010-07-22T14:58:15.080 に答える
2

誰も言及していないように、データの検証や変数のロックに使用できます。

  • 検証

    string _password;
    string Password
    {
        get { return _password; }
        set
        {
            // Validation logic.
            if (value.Length < 8)
            {
                throw new Exception("Password too short!");
            }
    
            _password = value;
        }
    }
    
  • ロック

    object _lock = new object();
    object _lockedReference;
    object LockedReference
    { 
        get
        {
            lock (_lock)
            {
                return _lockedReference;
            }
        }
        set
        {
            lock (_lock)
            {
                _lockedReference = value;
            }
        }
    }
    

    注:参照をロックする場合、参照されるオブジェクトのメンバーへのアクセスはロックされません。

遅延参照:遅延読み込みを行う場合、非同期で実行する必要が生じる可能性がありますが、現在はAsyncLazyがあります。Visual Studio SDK 2015より古いバージョンを使用している場合、または使用していない場合は、 AsyncExのAsyncLazyを使用することもできます。

于 2018-08-25T01:59:52.797 に答える
1

もう1つの使用法は、値を設定するときにいくつかの追加操作を行うことです。

私の場合、WPFで、プライベートオブジェクト(実装されていないINotifyPropertyChanged)に基づいて情報を表示すると、次のようになります。

private MyAggregateClass _mac;

private MyAggregateClass Mac
{
    get => _mac;
    set
    {
        if(value == _mac) return;
        _mac = value;
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(DisplayInfo)));
    }
}

public string DisplayInfo => _mac.SomeStringInformationToDisplayOnUI;
        

また、次のようなプライベートな方法もあります。

private void SetMac(MyAggregateClass newValue)

それをするために。

于 2020-11-12T16:47:54.667 に答える
0

明示的なフィールドのよりエキゾチックな使用法には、次のものがあります。

  • 使用するrefout、値を指定する必要があります-おそらくそれはInterlockedカウンターだからです
  • これは、たとえば明示的なレイアウトを使用して基本的なレイアウトを表すことを目的structとしています(おそらく、C ++ダンプまたはunsafeコードにマップするため) 。
  • 歴史的に、このタイプはBinaryFormatter自動フィールド処理で使用されてきました(auto-propsに変更すると名前が変更され、シリアライザーが壊れます)
于 2019-05-23T14:05:54.947 に答える
0

ガイドライン(プロパティ(C#プログラミングガイド))を見ると、プロパティをプライベートメンバーとして使用することを誰も期待していないようです。

プロパティを使用すると、クラスは、実装コードまたは検証コードを非表示にしながら、値を取得および設定するための公的な方法を公開できます。

いずれの場合も、1つまたは2つの方法で交換でき、その逆も可能です。

したがって、その理由は、設定時にフィールド構文を取得および取得する際に括弧を惜しまないためである可能性があります。

于 2020-11-26T15:01:51.823 に答える
0

怠惰なメンバーを実装するためのプロパティの使用については、さまざまな回答があります。そして、この回答では、プロパティを使用してライブエイリアスを作成する方法について説明しました。これらの2つの概念が時々一緒になることを指摘したかっただけです。

プロパティを使用して別のオブジェクトのパブリックプロパティのエイリアスを作成する場合、そのプロパティの遅延は保持されます。

[DebuggerBrowsable(DebuggerBrowsableState.Never)]
private IDbConnection Conn => foo.bar.LazyDbConnection;

一方、コンストラクターでそのプロパティを取得すると、遅延の側面が無効になります。

Conn = foo.bar.LazyDbConnection;
于 2021-07-15T18:45:32.977 に答える