24

クラスを作成するときは、常に次のようにパブリック プロパティを介してプライベート フィールドを公開します。

private int _MyField;
public int MyField
{ get{return _MyField; }

次のように public フィールドを公開してもよいのはいつですか。

public int MyField;

私は Result という構造を作成しています。私の意図はこれを行うことです:

public Result(bool result, string message)
{
   Result = result;
   Message = message;
}

public readonly int Result;
public readonly int Message;

ベストプラクティスは何ですか? これをしても大丈夫ですか?

4

11 に答える 11

32

public フィールドが (静的) 定数である場合にのみ公開します。その場合でも、通常はプロパティを使用します。

「定数」とは、C# で「定数」として表現できるものだけでなく、読み取り専用で不変の値を意味します。

読み取り専用のインスタンス変数 (Result や Message など) でさえ、ビュー内のプロパティにカプセル化する必要があります。

詳細については、この記事を参照してください。

于 2008-12-18T20:04:17.493 に答える
17

パブリック フィールドを使用するためのベスト プラクティスは何ですか?

「しないでください。」参照: 保護された属性は常に禁止されるべきですか? これは保護されたフィールドに関するものですが、公共のフィールドにはさらに当てはまります。

于 2008-12-18T20:04:04.357 に答える
9

プロパティを使用します。C# に自動プロパティがあるので簡単です。

于 2008-12-18T20:04:59.753 に答える
4

ベスト プラクティスは、いくつかの理由からプロパティを使用することです。まず、基礎となるデータ構造から API を分離します。次に、オブジェクトにバインドするフレームワークに組み込まれたものはすべて、フィールドではなくプロパティにバインドします。

他にも理由はあると思いますが、私には常にこの 2 つで十分です。

于 2008-12-18T20:03:00.193 に答える
3

やらないのがベストプラクティスだと思います。フィールドに直接アクセスする必要がある極端なパフォーマンスが必要でない限り、そうしないでください。

これについての良い記事は次のとおりです。

http://csharpindepth.com/Articles/Chapter8/PropertiesMatter.aspx

于 2008-12-18T20:04:35.653 に答える
2

これに似たものを使用することをお勧めします:

public class Result{  
    public bool Result {  get; protected set; }
    public string Message {  get; protected set; }

    public Result(bool result, string message) {
        Result = result;
        Message = message;
    }
}

このように、メンバー変数を宣言する必要はありません。コンパイラーに作業を任せてください。コードは非常にクリーンで短く、リファクタリングは簡単です。

于 2008-12-19T05:58:19.340 に答える
2

C スタイル言語 (C# など) では、プロパティを通じてフィールドを公開する必要があります。これは、VB.NET やその他の .NET 言語にも関係し、同じ基盤となるエンジンを共有しています。これを行う主な理由は、

Public MyField as Integer DOES NOT EQUAL Public Property MyField as Integer, .NET では、すべての状況で同じ動作をするわけではありません。

しかし、多くの人がパブリック フィールドを作成し続けているのをおそらく目にするでしょう。これの一部は、VB6 が COM を処理する方法によるものです。VB6 では、Public MyField as Integer は、Public Property MyField as Integer と同等です。両方が COM タイプ ライブラリに変換されると、両方が同じ方法で実装されるためです。

これにより、VB6 では、パブリック フィールドになる可能性のあるものに対して多くの奇妙な制限が発生しました。.NET や他の多くのオブジェクト指向言語にはない制限。これらの制限はコンパイル時にキャッチされるため、プログラマーが自分自身をいわば自分で撃つことを防ぎます。クラスが VB6 で非公開の場合、これらの制限の一部が緩和されましたが、すべてが緩和されたわけではありません。一般的なルールは、クラスとデータ型を public フィールドとしてのみ公開できるというものでした。

VB6 の遺産は、.NET に違いがあることを認識していないプログラマが多いことを意味します。

.NET はこの点で役に立たないため、すべてのフィールドがプロパティを通じて公開されていることを確認するという伝統的な手順を実行する必要があります。繰り返しますが、.NET ではフィールドはプロパティと同じではないためです。

この記事(他の人が指摘) では、.NET 側について説明しています。

于 2008-12-19T13:26:49.740 に答える
1

読み取り専用のアプローチについてお答えしたいと思います。

読み取り専用は、パブリック フィールドに get アクセサーのみを持つ方法ではありません。私は主に、コンストラクターからのみプライベート フィールドを設定できるプライベート フィールドで readonly を使用します。したがって、読み取り専用フィールドはコンストラクターでのみ設定できることを理解するために、アクセスすることしかできません。

ベスト プラクティスは、常にプロパティを使用して、コンストラクターの後にフィールドにアクセスすることです。したがって、クラス内からプロパティにアクセスする必要がある場合に備えて、次のようにします。

private readonly int result;
private readonly int message;

public Result(bool result, string message)
{
   this.result = result;
   this.message = message;
}

public int Result
{
   get{ return result; }
   private set { result = value; }
}

public int Message
{
   get{ return message; }
   private set { message = value; }
}

そうすれば、結果とメッセージのみを読み取ることができ、クラス内から書き込むことができます。

継承を使用する場合は、必要に応じてセットを保護することができます。

編集:質問で与えられたものに基づいて作成したコードを読んだ後、クラス名ResultがプロパティResultでエラーをスローする可能性があり、結果としてboolを受け取り、文字列を受け取っているというバグがありますコンストラクターでメッセージを送信しますが、それらを int で送信しようとすると、これは間違いなく機能しません。しかし、ここで価値があるのは、モルロジックです。

private readonly bool result;
private readonly string message;

public Answer(bool result, string message)
{
   this.result = result;
   this.message = message;
}

public bool Result
{
   get{ return result; }
   private set { result = value; }
}

public string Message
{
   get{ return message; }
   private set { message = value; }
}
于 2008-12-18T22:54:58.257 に答える
1

C#のフィールドとプロパティの違いは何ですか?

于 2008-12-18T20:03:17.730 に答える
0

一般に、型をデータ ホルダーとして使用する場合は、次のいずれかにする必要があります。

  1. 各フィールドが型の観点から値として動作し、フィールド値の任意の組み合わせが「意味をなす」場合、公開されたフィールドを持つ可変構造体。変更可能なクラス型への参照を保持するフィールドは、フィールドの目的が内容ではなく問題のオブジェクトのIDを保持することである場合に限定されることに注意してください。変更可能なフィールドを持つ構造体は、`SomeThing.SomeStruct.SomeField = anything` を `tempStruct = SomeThing.SomeStruct; と解釈する愚かな C# コンパイラの結果として、悪い評判を得ました。tempStruct.SomeField = anything` は診断を発行せずに実行されますが、今日のプログラマーが古代のコンパイラーが行うことについて心配する理由はありません。
  2. 上記が当てはまらず、データ項目全体を再生成してデータ項目の 1 つの側面を変更する必要があまりない場合に、非 public フィールドを持つ不変のクラスまたは構造体。
  3. それへの参照がそれを作成するエンティティの外部で永続化されない場合、変更可能なクラス (通常、そのような参照は外部コードに公開されるべきではありません)。変更可能なクラス型をデータ ホルダーとして使用するコレクション (単にオブジェクトの ID を格納するが、それらのオブジェクトが何を表しているかは気にしないコレクションとは対照的) であるため、他の 2 つのオプションが実行可能な場合は非常に優先されることに注意してください。多くの場合、コレクションに格納されているオブジェクトの防御コピーを作成し、オブジェクトが読み取られるたびに追加の防御コピーを作成する必要があります。構造体は、変更可能であるか「不変」であるかに関係なく、コレクションから格納または読み戻されるたびにコピーする必要がありますが、そのようなコピーは、構造体のサイズに関係なく安価です。、可変クラスを使用する場合に必要な防御コピーよりも。

可変クラスを使用する以外に実用的な方法がない場合、パブリック フィールドを公開するかどうかは、任意のバージョンのクラスでプロパティ セッターに検証ロジックを含める必要性が予見できるかどうか、およびメンバーの型が値型またはクラス型になります。Boundsが 型のパブリック フィールドである場合、次Rectangleのような式は、他のメンバーにアクセスすることなく、四角形の にアクセスできますSomeClass.Bounds.WidthWidth対照的にBounds、プロパティ (変更可能なものであっても) の場合、その式は の 4 つのメンバーすべてBoundsを一時構造体にコピーしてから、そのWidthフィールドにアクセスする必要があります。

于 2012-07-16T20:09:21.343 に答える
0

私が与える答えは、プロパティはよりリファクタリングしやすいということです。

読み取り専用フィールドを含むアセンブリがある場合は、それらをプロパティに変更します。フィールド (現在はプロパティ) にアクセスする別のアセンブリがある場合、それらはコンパイルなしでは機能しません。コンパイラに関する限り、フィールドとプロパティは同じではありません。

リファクタリングに戻ると、プロパティから始めたとします。ここで、データの取得元を変更する必要があります (別のクラスからアクセスします)。フィールドを扱っていた場合、それを実現する方法についていくつかの難しい決定を下す必要があります。プロパティは、ロジックを隠すことができるため、はるかに寛容です。

于 2008-12-18T23:31:46.560 に答える