web-dev-qa-db-ja.com

同じ名前の名前空間とクラス?

私はライブラリプロジェクトを編成しており、Scenegraphという名前の中央マネージャークラスと、Scenegraph名前空間に存在する他のクラスが多数あります。

私が本当に欲しいのは、シーングラフをMyLib.Scenegraphにし、他のクラスをMyLib.Scenegraph.*にすることですが、それを行う唯一の方法は、他のすべてのクラスをScenegraphの内部クラスにすることですScenegraph.csファイルで、それはあまりにも扱いにくいです。

代わりに、Mylib.Scenegraph.ScenegraphおよびMyLib.Scenegraph.*として整理しましたが、どのような動作をしますか。クラスと名前空間のどちらを参照しているかについて、Visual Studioは特定の条件下で混乱します。

このパッケージを整理する良い方法はありますか?メンテナンス不可能な混乱で私のコードを一緒にグロミングすることなくユーザーに便利ですか?

82
user430788

クラスに名前空間のような名前を付けることはお勧めしません。 this を参照してください。

フレームワークの設計ガイドラインでは、セクション3.4で「名前空間とその名前空間の型に同じ名前を使用しないでください」とあります。あれは:

namespace MyContainers.List 
{ 
    public class List { … } 
}

この悪さはなぜですか?ああ、方法を数えてみましょう。

あるものを参照していると思うが、実際には別のものを参照している状況に陥ることがあります。このような不幸な状況に陥ったとしましょう。Blah.DLLを作成し、Foo.DLLとBar.DLLをインポートしていますが、残念ながらどちらもFooと呼ばれるタイプを持っています。

// Foo.DLL: 
namespace Foo { public class Foo { } }

// Bar.DLL: 
namespace Bar { public class Foo { } }

// Blah.DLL: 
namespace Blah  
{   
using Foo;   
using Bar;   
class C { Foo foo; } 
}

コンパイラーはエラーを出します。 「Foo」はFoo.FooとBar.Fooの間であいまいです名前を完全に修飾することで修正するでしょう。

   class C { Foo.Foo foo; } 

これにより、「Foo.FooのFooはFoo.FooとBar.Fooの間であいまいです」というあいまいなエラーが発生します。最初のFooが何を指しているのかはまだわかりません。それがわかるまでは、2番目のFooが何を指しているのかわからなくてもかまいません。

98
pinckerman

名前空間とクラスに同じ名前を付けると、他の人が言ったようにコンパイラを混乱させる可能性があります。

名前を付けるには?

名前空間に複数のクラスがある場合、それらすべてのクラスを定義する名前を見つけます。

名前空間にクラスが1つしかない(したがって、同じ名前を付ける誘惑)名前空間に名前を付けるClassName NS。これは、Microsoftが少なくとも名前空間に名前を付ける方法です。

9
GoTo

Microsoft.public.dotnet.languages.csharpおよびMyLib.ScenegraphUtil.Scenegraphを使用するには、MyLib.ScenegraphUtil.*で得たアドバイスに従うことをお勧めします。

8
Ant_222

CA1724: Type Names Should Not Match Namespaces ...

基本的に、適切なコーディングのためにコード分析に従うと、このルールはあなたがやろうとしていることをしないと言います。コード分​​析は 非常に便利 あなたが見つけるのを助けることで 潜在的な 問題。

5
m-y

私の2セントを追加するだけです:

次のクラスがありました。

namespace Foo {
    public struct Bar {
    }
    public class Foo {
        //no method or member named "Bar"
    }
}

クライアントは次のように書かれています。

using Foo;

public class Blah {
    public void GetFoo( out Foo.Bar[] barArray ) {
    }
}

Outパラメーターを使用する代わりに出力を返さないGetFooエラーを許容するため、コンパイラーはデータ型Foo.Bar []を解決できませんでした。エラーを返していました:型または名前空間Foo.Barが見つかりませんでした。

コンパイルしようとすると、Fooがクラスとして解決され、Fooクラスに埋め込みクラスBarが見つからなかったようです。また、Foo.Barという名前空間も見つかりませんでした。名前空間FooでクラスBarを探すことに失敗しました。名前空間のドットは構文ではありません。文字列全体はトークンであり、ドットで区切られた単語ではありません。

この動作は、.Net 4.6を実行するVS 2015によって示されました。

4
Steve

古い投稿ですが、ここでは誰かを助けるかもしれない別のアイデアに行きます:

「...しかし、それを行う唯一の方法は、Scenegraph.csファイル内の他のすべてのクラスをScenegraphの内部クラスにすることであり、それはあまりにも扱いにくいです。」

これは、多くのシナリオにとって本当に優れた実装です。しかし、同じ.csファイルにすべてのコードを配置するのは面倒です(控えめに言っても)。

基本クラスを「部分クラス」にしてから、独自のファイルで内部クラスを作成することで解決できます(基本クラスの補数を宣言してから特定の内部クラスを使用する必要があることに注意してください)そのファイル用)。

何かのようなもの...

Scenegraph.cs:

namespace MyLib
{
    public partial class Scenegraph
    {
        //Scenegraph specific implementations
    }
}

DependentClass.cs:

namespace MyLib
{
    public partial class Scenegraph
    {
        public class DependentClass
        {
            //DependentClass specific implementations
        }
    }
}

これは、1つの巨大で乱雑なファイル内のすべてを乱雑にすることなく、内部クラスのクリーンな実装を実現できると考えています。

0
Marcelo Myara

他の人が言ったように、名前空間と同じ名前のクラスを避けることは良い習慣です。

ここにいくつかの追加の命名の提案がありますから svickによる回答 ソフトウェアの関連する質問「同じクラスと名前空間名」へエンジニアリングスタック交換:

名前空間に含まれる型と同じ名前を名前空間に付けないでください。使用できるアプローチはいくつかあると思います。

  • 複数化:Model.DataSources.DataSource

これは、名前空間の主な目的が同じ基本型から継承する型を含むか、同じインターフェイスを実装することである場合に特にうまく機能します。

  • 短縮:Model.QueryStorage

名前空間に含まれる型の数が少ない場合、その名前空間はまったく必要ないかもしれません。

  • 企業化:Model.ProjectSystem.Project

これは、特に製品の重要な部分である機能に対して機能するため、独自の名前に値します。

(上記の回答では、Model.DataSource.DataSourceではなくModel.QueryStorage.QueryStorage.Model.Project.Project、およびMyLib.Scenegraph.Scenegraphを例として使用しています。)

(私はまた、ここの他の回答で他の命名の提案が役立つことを発見しました。)

0
sonny