80

これを行う C# クラスのサンプル コードがたくさんあります。

public class Point {
    public int x { get; set; }
    public int y { get; set; }
}

または、古いコードでは、明示的なプライベート バッキング値を使用し、新しい自動実装プロパティを使用しない場合と同じです。

public class Point {
    private int _x;
    private int _y;

    public int x {
        get { return _x; }
        set { _x = value; }
    }

    public int y {
        get { return _y; }
        set { _y = value; }
    }
}

私の質問はなぜですか。上記を実行することと、以下のようにこれらのメンバーをパブリック フィールドにすることの間に機能的な違いはありますか?

public class Point {
    public int x;
    public int y;
}

明確にするために、基になるデータの変換を行う必要がある場合のゲッターとセッターの価値を理解しています。ただし、値を渡すだけの場合は、不必要に冗長に見えます。

4

17 に答える 17

53

これは私たちのチームがまだ解決していない問題であり、コーディング標準は依然としてすべてのクラスに対して詳細なプロパティを主張していますが、私は同意する傾向があります (不必要に冗長に思えます)。

ジェフ・アトウッドは数年前にこれに対処しました。彼が遡及的に指摘した最も重要な点は、フィールドからプロパティへの変更はコードの重大な変更であるということです。それを消費するものはすべて、新しいクラス インターフェイスで動作するように再コンパイルする必要があります。そのため、制御できないものがクラスを消費している場合、問題が発生する可能性があります。

于 2008-09-21T17:29:26.907 に答える
31

また、後でこれに変更する方がはるかに簡単です。

public int x { get; private set; }
于 2008-09-21T17:28:18.903 に答える
10

これらのメンバーの設定とアクセスをカプセル化します。今後、コードの開発者がメンバーにアクセスまたは設定するときにロジックを変更する必要がある場合は、クラスのコントラクトを変更せずに変更できます。

于 2008-09-21T17:26:08.100 に答える
8

基礎となるデータ構造を変更する必要がある場合でも、クラスへのパブリック インターフェイスを変更する必要はありません。

C# では、プロパティと変数の扱いが異なる場合があります。たとえば、プロパティを ref または out parameters として渡すことはできません。したがって、何らかの理由でデータ構造を変更する必要があり、パブリック変数を使用していて、プロパティを使用する必要がある場合、インターフェイスを変更する必要があり、プロパティ x にアクセスするコードは、変数のときのようにコンパイルできなくなる可能性があります。バツ:

Point pt = new Point();
if(Int32.TryParse(userInput, out pt.x))
{
     Console.WriteLine("x = {0}", pt.x);
     Console.WriteLine("x must be a public variable! Otherwise, this won't compile.");
}

最初からプロパティを使用すると、これを回避できます。また、クライアント コードを壊すことなく、基礎となる実装を必要なだけ自由に微調整できます。

于 2008-09-21T17:42:05.877 に答える
5

セッターとゲッターを使用すると、追加の抽象化レイヤーを追加できます。純粋な OOP では、オブジェクトが外部に提供しているインターフェイスを介して常にオブジェクトにアクセスする必要があります...

次のコードを検討してください。これにより、asp.net で節約でき、セッターとゲッターによって提供される抽象化のレベルがなければ不可能です。

class SomeControl
{

private string _SomeProperty  ;
public string SomeProperty 
{
  if ( _SomeProperty == null ) 
   return (string)Session [ "SomeProperty" ] ;
 else 
   return _SomeProperty ; 
}
}
于 2009-04-22T14:22:29.987 に答える
5

自動実装されたゲッターは、プロパティと実際のプライベート ストレージ変数に同じ名前を使用するためです。今後どう変えていくか。getter と setter にロジックを追加する必要がある場合に備えて、フィールドの代わりに実装された auto を使用して、将来変更できるようにすることがポイントだと思います。

例えば:

public string x { get; set; }

たとえば、すでに xa を何度も使用していて、コードを壊したくないとします。

自動ゲッターセッターをどのように変更しますか...たとえば、セッターの場合、有効な電話番号形式の設定のみを許可します...クラスのみが変更されるようにコードを変更するにはどうすればよいですか?

私の考えは、新しいプライベート変数を追加し、同じ x ゲッターとセッターを追加することです。

private string _x;

public string x { 
    get {return _x}; 
    set {
        if (Datetime.TryParse(value)) {
            _x = value;
        }
    }; 
}

柔軟にするって、そういうことですか?

于 2009-09-08T01:42:19.117 に答える
2

また、バインドとシリアル化に関しては、パブリック メンバーへの変更の影響も考慮する必要があります。これらは両方とも、多くの場合、パブリック プロパティに依存して値を取得および設定します。

于 2008-09-21T17:50:42.050 に答える
2

また、ゲッターとセッターにはブレークポイントを設定できますが、フィールドには設定できません。

于 2009-09-08T01:45:53.663 に答える
1

私の知る限り、生成されたCILインターフェースは異なります。パブリック メンバーをプロパティに変更すると、それはパブリック インターフェイスであり、そのクラスを使用するすべてのファイルを再構築する必要があります。ゲッターとセッターの実装のみを変更する場合、これは必要ありません。

于 2008-09-21T17:44:17.307 に答える
1

おそらく、フィールドを公開するだけで、より貧弱なドメインモデルにつながる可能性があります。

敬具

于 2008-09-21T17:55:23.473 に答える
1

また、自動プロパティを読み取り専用にすることはできず、インラインで初期化することもできないことに注意してください。これらは両方とも、.NET の将来のリリースで見たいものですが、.NET 4.0 ではどちらもできないと思います。

最近、プロパティでバッキング フィールドを使用するのは、クラスが INotifyPropertyChanged を実装し、プロパティが変更されたときに OnPropertyChanged イベントを発生させる必要があるときだけです。

また、これらの状況では、値がコンストラクターから渡されるときにバッキング フィールドを直接設定します (OnPropertyChangedEvent を試行して起動する必要はありません (現時点ではとにかく NULL になります)、それ以外の場所ではプロパティ自体を使用します)。

于 2009-09-08T02:10:55.137 に答える
0

後でデータの翻訳が不要になるかどうかはわかりません。メンバーを非表示にすれば、その準備はできています。インターフェイスが同じままであるため、クラスのユーザーは翻訳を追加しても気付かないでしょう。

于 2008-09-21T17:26:41.093 に答える
0

最大の違いは、内部構造を変更した場合でも、API のユーザーを傷つけることなく内部ロジックを変更して、getter と setter をそのまま維持できることです。

于 2008-09-21T17:27:14.540 に答える
0

この場合、x と y の取得方法を変更する必要がある場合は、後でプロパティを追加するだけです。これは私が最も混乱していることです。パブリック メンバー変数を使用すると、後で簡単にプロパティに変更できます。また、値を内部に格納する必要がある場合は、_x および _y というプライベート変数を使用できます。

于 2008-09-21T17:31:57.197 に答える
0

セッターとゲッターは原則として悪いものです (それらは OO の悪臭です。アンチパターンであるとは言いません。なぜなら、それらは本当に必要な場合があるからです)。

いいえ、技術的には違いはありません。最近、オブジェクトへのアクセスを本当に共有したい場合は、getter を追加する代わりに public final にすることがあります。

セッターとゲッターが「売却」された方法は、誰かが値を取得しているか、値を変更していることを知る必要がある場合があるということです。これは、プリミティブでのみ意味があります。

DAO、DTO、表示オブジェクトなどのプロパティ バッグ オブジェクトは、この規則から除外されます。これは、オブジェクトという単語の実際の「OO 設計」意味におけるオブジェクトではないためです。(DTO や Bean に「メッセージを渡す」ことは考えていません。これらは、設計上、単に属性/値のペアの山です)。

于 2008-09-23T20:58:57.570 に答える