簡體   English   中英

命名空間和類同名?

[英]Namespace and class with the same name?

我正在組織一個庫項目,我有一個名為Scenegraph的中央管理器類和一大堆位於 Scenegraph 命名空間中的其他類。

我真正想要的是MyLib.ScenegraphMyLib.Scenegraph和其他類是MyLib.Scenegraph.* ,但似乎唯一的方法是讓所有其他類成為Scenegraph內部類Scenegraph.cs 文件,這太笨拙了。

相反,我已將其組織為Mylib.Scenegraph.ScenegraphMyLib.Scenegraph.* ,這可以正常工作,但我發現 Visual Studio 在某些情況下會混淆我是指類還是命名空間。

有沒有一種好方法來組織這個包,這樣用戶就可以方便地使用我的所有代碼,而不會將我的所有代碼放在一個無法維護的混亂中?

我不建議你像它的命名空間一樣命名一個類,參見這篇文章

框架設計指南在 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 in Foo.Foo is ambiguous between Foo.Foo and Bar.Foo ”。 我們仍然不知道第一個 Foo 指的是什么,在我們弄清楚之前,我們甚至不會費心去弄清楚第二個指的是什么。

為命名空間和類提供相同的名稱可能會像其他人所說的那樣混淆編譯器。

那怎么命名呢?

如果命名空間有多個類,則找到定義所有這些類的名稱。

如果命名空間只有一個類(因此很想給它同一個名字)命名命名空間ClassName NS 這至少是微軟命名他們的命名空間的方式。

我建議您按照我在microsoft.public.dotnet.languages.csharp上獲得的建議使用MyLib.ScenegraphUtil.ScenegraphMyLib.ScenegraphUtil.*

盡管我同意其他答案,因為您不應將類命名為與命名空間相同的名稱,但有時您無法遵守此類要求。

例如,在我的情況下,我不是做出這樣決定的人,因此我需要找到一種方法來讓它發揮作用。

因此,對於那些無法更改命名空間名稱或類名稱的人來說,這里是一種使您的代碼工作的方法。

// 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 的“混淆”消失了。

注意:如果在您的控制范圍內,您應該避免這種命名沖突。 僅當您無法控制相關類和命名空間時,才應使用上述技術。

CA1724: Type Names Should Not Match Namespaces ...

基本上,如果您遵循代碼分析進行正確編碼,則此規則表示不要做您想做的事情。 代碼分析對於幫助您發現潛在問題非常有用

只需添加我的 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 不返回輸出而不是使用 out 參數,編譯器無法解析數據類型 Foo.Bar[] 。 它返回錯誤:找不到類型或命名空間 Foo.Bar 。

似乎當它嘗試編譯時將 Foo 解析為類,並且在類 Foo 中沒有找到嵌入的類 Bar。 它也找不到名為 Foo.Bar 的命名空間。 它未能在命名空間 Foo 中查找類 Bar。 名稱空間中的點不是句法上的。 整個字符串是一個標記,而不是由點分隔的單詞。

運行 .Net 4.6 的 VS 2015 表現出這種行為

舊帖子,但在這里我提出了另一個可能對某人有所幫助的想法:

“...但似乎唯一的方法是在 Scenegraph.cs 文件中使所有其他類成為 Scenegraph 的內部類,這太笨拙了。”

對於許多場景來說,這確實是更好的實現。 但是,我確實同意將所有代碼放在同一個 .cs 文件中很煩人(至少可以這么說)。

您可以通過使基類成為“部分類”來解決它,然后繼續在自己的文件上創建內部類(請記住,他們必須聲明基類補充,然后繼續使用特定的內部類對於那個文件)。

就像是...

場景圖.cs:

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

依賴類.cs:

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

我確實認為這更接近於擁有內部類的干凈實現,而不必將所有內容都放在一個龐大而凌亂的文件中。

正如其他人所說,避免將類命名為其命名空間是一種很好的做法。

以下是svick對 Software Engineering Stack Exchange 上相關問題“Same class and namespace name” 的回答中的一些額外命名建議

您不應該將命名空間命名為與其包含的類型相同的名稱,這是對的。 我認為您可以使用幾種方法:

  • 復數:Model.DataSources.DataSource

如果命名空間的主要目的是包含從相同的基類型繼承或實現相同的接口的類型,則這種方法特別有效。

  • 縮短:Model.QueryStorage

如果命名空間僅包含少量類型,則您可能根本不需要該命名空間。

  • 使企業化:Model.ProjectSystem.Project

這尤其適用於作為產品重​​要組成部分的功能,因此它們值得擁有自己的名字。

(請注意,上述答案使用Model.DataSource.DataSourceModel.QueryStorage.QueryStorage.Model.Project.Project作為示例,而不是MyLib.Scenegraph.Scenegraph 。)

(我還發現此處其他答案中的其他命名建議很有幫助。)

當它是命名空間的主類時會發生這種情況。 因此,將命名空間放在庫中是一種動機,如果將“Lib”添加到命名空間名稱中,問題就會消失......

namespace SocketLib
{
    class Socket
    {

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM