ネストタイプは悪い習慣と見なされますか?


8

タイトルに示されているように、ネストタイプ(クラスの列挙型や構造体など)は悪い習慣と見なされていますか?Visual Studioでコード分析を実行すると、次のメッセージが返されます。

警告34 CA1034:Microsoft.Design:タイプ 'ClassName.StructueName'をネストしないでください。または、外部から見えないようにアクセシビリティを変更します。

ただし、コード分析の推奨事項に従うと、単一のクラスにのみ適用されるか、またはそのクラスでのみ使用される可能性のある構造体および列挙型がアプリケーション内に多数存在する傾向があることがわかりました。そのような場合、その場合はタイプsinをネストするのが適切でしょうか、それともより良い方法がありますか?


この質問は、programmers.stackexchange.com / questions / 34067に非常に密接に関連しています。 これを複製として閉じるかどうか悩んでいます...
Walter

@ウォルター-それらは近いですが、クラスでクラスをネストすることと、クラスで他のすべての型を個別にネストすることで害を及ぼさないように個別に持ち上がる質問を聞いたことがあります。結局のところ、最初に検索を行ったときには、その質問は見つかりませんでした。
rjzii

回答:


15

ネストされた型は悪くありません。受け取った警告は、ネストされたタイプがないことを示唆するものではありません。これは単に、ネストされた型が適切なアクセス修飾子とコードの場所を使用する必要があることを示しています。

ネストされた型が本当に包含クラス内でのみ使用される場合(つまり、それが内部データコンテナーまたはステータスインジケーターである場合)、そのアクセス修飾子をプライベートに設定します。

ネストされた型が1つ以上のメソッドシグネチャの一部である場合、それは実際には包含クラスに対してローカルではありません。これは、包含クラスのインスタンスとの間でやり取りされるメッセージを表します。この場合、ネストされた型を包含クラスの外に移動し、内部やパブリックなどのよりオープンなアクセス修飾子を与える方が間違いなく良いでしょう。

つまり、警告はローカルタイプをプライベートにし、共有タイプはスタンドアロンにすることを推奨しているようです。


内部修飾子は、私がほとんどの場合に行ってきたもので、少しクリーンアップされていますが、多くのものがアプリケーション内に浮かんでいます。
rjzii

1

それがそのクラスによってのみ使用される場合、それはプライベートにされるべきであり、それはまさにメッセージが示唆していることです。


それが行われる場合もあれば、クラスにアタッチされたメソッド呼び出しで列挙型が使用される場合もあります。同様に、パラメーターの数が指定された数を超える場合、メソッドクラスに使用される構造も見ました。
rjzii

0

タイプのネストに関する警告は、コード分析を有効にしてからしばらくしてから受け取った最初の「提案」の1つでした。それが私がそれをオフにした理由でもありました。

一部の提案は、まるで別の惑星からのものであるかのように、実際には外国のものです。

列挙型をクラスの中に入れて、物事を論理的にまとめます。

このように考えてください:ネスト型がすべてのケースで絶対に悪であるなら、なぜ言語設計者はそもそもそれを実装したのでしょうか?これは多くの場合に有用であり、その点で上記の警告は、コード内の何かが最適ではない可能性があることを指摘するだけです。それが当てはまるかどうかはあなた次第です。


2
名前空間は、列挙型の論理グループにする必要があります。クラスではない
アーロン・マクイバー、2011年

1
まあ、状況によっては不便だと思います。

現在列挙型をクラス内に配置している場合、それをクラス外に移動して名前空間内に常駐させると、すべてのCTRL + XとCTRL + Vが結合されます。
アーロンマクイバー、2011年

列挙型をクラスに入れることもあります。私にはそれに正当な理由があると思います-それは厳密な規則ではありません。
2011年

3
@rmx単一のクラス内で列挙型を使用したことはありません。これは常に複数のクラス内で使用されるため、名前空間内で独自のエンティティとして定義する方がはるかに理にかなっています。
アーロンマクイバー、2011年

0

番号

C#の良い例はIEnumerableです。他のクラスは、それが返す正確なクラスを知る必要はありません。IEnumeratorであるということだけです。したがって、ネストされたクラスにすることは理にかなっています。そうでない場合、IEnumeratorを実装するIntelliSenseに多数の小さなクラスが浮かんでいる可能性があります。


場合によっては、コンパイラがによって返される型を知っていると、実行時の効率が向上することがありGetEnumerator()ます。そのため、をList<T>.GetEnumerator()返しますList<T>.Enumerator()。他のいくつかの名前のメソッドを使用するようにコンパイラを依頼するいくつかの方法であった場合、その方法の例を持っている方が良かったかもしれませんForEachGetEnumerator()リターンをList<T>.Enumeratorして持ってGetEnumerator()リターンをIEnumerator<T>、しかし、メカニズムはそのために存在しません。
スーパーキャット2014年
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.