web-dev-qa-db-ja.com

保護されたメンバー/フィールドは本当に悪いですか?

ここで、MSDN for C#の命名規則を読むと、パブリックフィールドおよび保護フィールドよりもプロパティが常に優先されることが示されていることがわかります。パブリックフィールドや保護フィールドは絶対に使用しないでくださいと言われたこともあります。パブリックフィールドが必要な理由はまだ見つかっていませんが、保護されたフィールドは本当に悪いのでしょうか。

値を取得/設定するときに特定の検証チェックが実行されることを確認する必要があるかどうかはわかりますが、多くの場合、私の意見では余分なオーバーヘッドのように見えます。つまり、baseName、prefixName、suffixNameのフィールドを持つクラスGameItemがあるとします。プロパティの作成の両方のオーバーヘッドを取る必要があるのはなぜですか(C#)またはアクセサメソッドとパフォーマンスへの影響が発生します(アプリケーションのすべてのフィールドに対してこれを行うと、特にPHPやゲームのようにパフォーマンスのある特定のアプリケーションは重要ですか?

31
ryanzec

保護されたメンバー/フィールドは本当に悪いですか?

いいえ。彼らはずっと悪いです。

メンバーがprivateよりもアクセスしやすくなるとすぐに、そのメンバーがどのように動作するかについて他のクラスに保証します。フィールドは完全に制御されていないため、フィールドを「公開」すると、クラスと、クラスから継承またはクラスと相互作用するクラスが開かれ、バグのリスクが高くなります。フィールドがいつ変更されるかを知る方法はなく、誰が、または何がフィールドを変更するかを制御する方法もありません。

現在、または将来のある時点で、コードのいずれかが特定の値のフィールドに依存する場合は、期待値でない場合に備えて、有効性チェックとフォールバックロジックを追加する必要があります-使用するすべての場所。代わりにそれをいまいましいプロパティにすることができたとき、それは膨大な量の無駄な努力です;)

最良派生クラスと情報を共有する方法は読み取り専用プロパティ:です。

protected object MyProperty { get; }

絶対に持っている場合は、読み取り/書き込みを行わないでください。本当に本当に読み取り/書き込みにする必要がある場合は、デザインを再考してください。それでも読み書きが必要な場合は、同僚に謝罪し、二度としないでください:)

多くの開発者は、これは過度に厳格であると信じており、あなたに言うでしょう。そして、これほど厳密でなくても、でうまくいくことができるのは事実です。しかし、このアプローチを取ることは、あなたがただ通り抜けるだけから非常に堅牢なソフトウェアに移行するのを助けるでしょう。バグの修正に費やす時間がはるかに少なくなります。

そして、パフォーマンスに関する懸念については、そうしないでください。キャリア全体で、ボトルネックがコールスタック自体になるほど速くコードを記述しないことを保証します。

80
Rex M

OK、反対票を投じてください。

  • まず第一に、プロパティがパフォーマンスを損なうことはありません(プロパティがあまり機能しない場合)。それは他の誰もが言うことです、そして私は同意します。

  • もう1つのポイントは、プロパティにブレークポイントを配置して、取得/設定イベントをキャプチャし、それらがどこから来ているかを見つけることができるという点で優れていることです。

残りの議論はこのように私を悩ませます:

  • 彼らは「名声による議論」のように聞こえます。 MSDNがそれを言う場合、または誰もが好きな有名な開発者や作者がそれを言う場合、それは必須そうです。

  • これらは、データ構造には一貫性のない状態が多数あるという考えに基づいており、さまよったり、それらの状態に置かれたりしないように保護する必要があります。 (私には)データ構造は現在の教育では非常に強調されているので、通常はdoこれらの保護が必要です。はるかに好ましいのは、データ構造を最小化するであり、正規化され、一貫性のない状態にならないようにすることです。次に、クラスのメンバーが変更された場合、それは破損するのではなく、単に変更されます。結局のところ、どういうわけか多くの優れたソフトウェアがCで書かれており、保護の欠如にそれほど悩まされることはありませんでした。

  • それらは極端に運ばれる防御的なコーディングに基づいています。それは、あなたのクラスが、他の誰のコードもあなたのものをガチョウにしないと信頼できない世界で使用されるという考えに基づいています。これが本当である状況があると確信しています、しかし私はそれらを見たことがありません。私が見たのは持っている必要のない保護を回避するために物事がひどく複雑になり、ひどく過度に複雑で正規化されていないデータ構造の一貫性を守ろうとする状況です。

26
Mike Dunlavey

フィールドとプロパティに関して、パブリックインターフェイスでプロパティを優先する理由は2つ考えられます(保護されているのは、クラスだけでなく他の誰かが見ることができるという意味でもパブリックです)。

  • プロパティを公開すると、実装を非表示にする方法が提供されます。また、それを使用するコードを変更せずに実装を変更することもできます(たとえば、データがクラスに格納される方法を変更する場合)

  • リフレクションを使用してクラスを操作する多くのツールは、プロパティのみに焦点を当てています(たとえば、シリアル化用の一部のライブラリはこのように機能すると思います)。プロパティを一貫して使用すると、これらの標準の.NETツールを簡単に使用できるようになります。

オーバーヘッドについて:

  • ゲッター/セッターがフィールドの値を単に読み取る/設定する通常の1行のコードである場合、JITは呼び出しをインライン化できるはずなので、パフォーマンスが過剰になることはありません。

  • 自動的に実装されたプロパティ(C#3.0以降)を使用すると、構文上のオーバーヘッドが大幅に削減されるため、これは問題ではないと思います。

    protected int SomeProperty { get; set; }
    

    実際、これにより、たとえばsetprotectedやgetを非常に簡単に公開できるため、フィールドを使用するよりもさらにエレガントになります。

6
Tomas Petricek

パブリックフィールドや保護フィールドは、検証なしで宣言クラスの外部から操作できるため、不適切です。したがって、それらはオブジェクト指向プログラミングのカプセル化の原則を破っていると言えます。

カプセル化を失うと、宣言クラスのコントラクトが失われます。クラスが意図または期待どおりに動作することを保証することはできません。

プロパティまたはメソッドを使用してフィールドにアクセスすると、カプセル化を維持し、宣言するクラスのコントラクトを実行できます。

5
Håvard S

読み取り専用プロパティの回答に同意します。しかし、ここで悪魔の代弁者を演じるには、それは本当にあなたがしていることに依存します。私は常にパブリックメンバーと一緒にコードを書いていることを認めてうれしく思います(コメントしたり、ガイドラインに従ったり、手続きをしたりすることもありません)。

しかし、私が仕事をしているとき、それは別の話です。

0

実際には、クラスがデータクラスであるか動作クラスであるかによって異なります。

動作とデータを分離しておく の場合、動作がない限り、データクラスのデータを公開しても問題ありません。

クラスがビヘイビアークラスの場合、データを公開しないでください。

0
Mongus Pong