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


95

私はライブラリプロジェクトを整理していますが、中央マネージャークラスという名前Scenegraphのほか、Scenegraph名前空間に存在する他のクラスもたくさんあります。

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

代わりに、私はそれをMylib.Scenegraph.Scenegraphand として整理しましたがMyLib.Scenegraph.*、どの種類の作品ですか?Visual Studioは、クラスと名前空間のどちらを参照しているかについて、いくつかの条件下で混乱します。

このパッケージを整理する良い方法はありますか?そうすれば、維持できない混乱の中ですべてのコードをひとまとめにすることなく、ユーザーにとって便利になりますか?

回答:


112

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

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

namespace MyContainers.List 
{ 
    public class List {  } 
}

なぜこれが悪いのですか?ああ、道を数えてみましょう。

自分が1つのことに言及していると思うが、実際には別の何かに言及している状況に陥る可能性があります。この不幸な状況に陥ったとしましょう。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 in Foo.FooのFooはFoo.FooとBar.Fooの間で曖昧です」というあいまいなエラーが発生します。最初のFooが何を指しているのかはまだわかりません。それがわかるまで、2番目のFooが何を指しているのかわからなくてもかまいません。


6
その興味深い点。私はそれについて反論します。ありがとう。「スタイルガイドが言う」で始まる正直な議論は私を感動させないでください。私はスタイルガイドに不当ながらくたをたくさん見ました。しかし、あなたは上記の良い実用的な議論をします。とにかく考える価値がある。
user430788 2013

5
応答には、「何をすべきでないか」と書かれています。一部のスタックユーザーは「何をすべきか」を探します。誰かがAnt_222の回答を勧めますか?
架空の話

3
本当に行き詰まっている場合でも、名前空間の外に型エイリアスを作成できます。外部エイリアスは、2つの完全に同一の完全な識別子(名前空間+クラス名)がある場合にのみ必要です。
ジェフリー

3
上記のすべてはさようならと意見です。事実はので、あなたはそれを行うべきではないということですC#コンパイラがそれを誤解されますに何が起こっているのかはっきり言われたにもかかわらず、。たとえば、using Foo.Bar;後で名前空間内のクラス(または列挙型)Bar bを非常に明確に参照しBarていますFoo.Bar。これを行わない本当の理由は、純粋にC#コンパイラがそれを正しく理解できないことです。これは、驚くほど不幸なことです。それ以外は羊毛状のアドバイスです。
TJクラウダー2016

2
わかりません。なぜFoo.Fooがあいまいなのですか?この特定のケースでは、名前空間FooのクラスFooを使用することをコンパイラーに直接言います。番号?
GuardianX

14

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

それをどのように命名するのですか?

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

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


4
マイクロソフトのそのような名前空間の例はありますか?
18

私はそれを検索し、あなたに戻って来なければなりません。
GoTo 2018

@sunefred検索しましたが見つかりませんでした。しかし、私は間違いなくドキュメントでそれを見たことを覚えています。名前空間に単一のクラスを持たせたい場合は多くないと思います。
GoTo

9

私はあなたが私が乗ったアドバイスに従うことを示唆しているmicrosoft.public.dotnet.languages.csharp使用MyLib.ScenegraphUtil.ScenegraphしてをMyLib.ScenegraphUtil.*


8

CA1724: Type Names Should Not Match Namespaces ...

基本的に、コード分析に従って適切なコーディングを行うと、このルールは、実行しようとしていることを実行しないことを示します。コード分​​析は、潜在的な問題を見つけるのに非常に役立ちます。


4

ちょうど私の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 ) {
    }
}

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

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

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


4

クラスに名前空間と同じ名前を付けてはいけないという点で他の回答に同意しますが、そのような要件に準拠できない場合があります。

たとえば私の場合、私はそのような決定を下す人ではなかったので、それを機能させる方法を見つける必要がありました。

したがって、名前空間名もクラス名も変更できない人のために、ここでコードを機能させることができます。

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

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

// Blah.DLL: 
namespace Blah
{
    using FooNSAlias = Foo;//alias
    using BarNSAlias = Bar;//alias
    class C { FooNSAlias.Foo foo; }//use alias to fully qualify class name
}

基本的に私は名前空間「エイリアス」を作成し、それによってクラスを完全に修飾することができ、Visual Studioの「混乱」はなくなりました。

注: このような名前の競合が発生した場合は、回避する必要があります。問題のクラスと名前空間を制御できない場合にのみ、前述の手法を使用してください。


2
それは不完全な世界への興味深い解決策だったので、私はそれを投票しました。
user430788

2

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

「...しかし、それを行う唯一の方法は、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つの巨大で乱雑なファイル内にすべてを散らかす必要がない一方で、内部クラスのクリーンな実装に到達できる方に近いと思います。


2

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

ソフトウェアエンジニアリングスタックエクスチェンジでの関連する質問「同じクラスと名前空間の名前」に対するsvickの回答からのいくつかの追加の命名提案は次のとおりです。

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

  • 複数形:Model.DataSources.DataSource

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

  • 短縮:Model.QueryStorage

名前空間に含まれる型の数が少ない場合、その名前空間はまったく必要ない可能性があります。

  • エンタープライズ化:Model.ProjectSystem.Project

これは、特に製品の重要な部分で機能するため、独自の名前を付けるのに適しています。

(上記の回答ではModel.DataSource.DataSourceModel.QueryStorage.QueryStorage.ではModel.Project.Projectなく、、、およびを例として使用していることに注意してくださいMyLib.Scenegraph.Scenegraph。)

(また、他の回答にある他の名前の提案も参考になりました。)


1

それが名前空間のメインクラスである場合に発生します。したがって、名前空間をライブラリに配置することが1つの動機です。名前空間名に「Lib」を追加すると、問題はなくなります...

namespace SocketLib
{
    class Socket
    {
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.