Подтвердить что ты не робот

Пространство имен и класс с тем же именем?

Я организую проект библиотеки, и у меня есть центральный менеджерский класс с именем Scenegraph и целая группа других классов, которые живут в пространстве имен Scenegraph.

Мне бы очень хотелось, чтобы сценарий был MyLib.Scenegraph, а остальные классы были MyLib.Scenegraph.*, но, похоже, единственный способ сделать это - сделать все остальные классы внутренними классами Scenegraph в файле Scenegraph.cs и это слишком громоздко.

Вместо этого я организовал его как Mylib.Scenegraph.Scenegraph и MyLib.Scenegraph.*, который работает, но я обнаружил, что Visual Studio запутывается при некоторых условиях относительно того, ссылаюсь ли я на класс или пространство имен.

Есть ли хороший способ организовать этот пакет, поэтому он удобен для пользователей, не скрывая весь мой код вместе в недостижимом беспорядке?

4b9b3361

Ответ 1

Я не рекомендую вам указывать класс, подобный его пространству имен, см. 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. Bummer. Думаю, я исправлю это, полностью присвоив имя:

   class C { Foo.Foo foo; } 

Теперь это дает ошибку двусмысленности " Foo в Foo.Foo неоднозначно между Foo.Foo и Bar.Foo". Мы все еще не знаем на что ссылается первый Foo, и пока мы не можем понять это, мы даже не потрудись попытаться выяснить, что второй относится к.

Ответ 2

Предоставление того же имени пространству имен и классу может запутать компилятор, как говорили другие.

Как назвать это тогда?

Если пространство имен имеет несколько классов, найдите имя, которое определяет все эти классы.

Если пространство имен имеет только один класс (и, следовательно, возникает искушение дать ему одно и то же имя), назовите пространство имен ClassName NS. Вот как Microsoft называет их пространства имен как минимум.

Ответ 3

Я предлагаю вам следовать рекомендациям, которые я получил в microsoft.public.dotnet.languages.csharp, для использования MyLib.ScenegraphUtil.Scenegraph и MyLib.ScenegraphUtil.*.

Ответ 4

CA1724: Type Names Should Not Match Namespaces...

По сути, если вы следуете Code Analysis для правильного кодирования, это правило говорит не делать то, что вы пытаетесь сделать. Анализ кода очень полезен для поиска потенциальных проблем.

Ответ 5

Просто добавьте мои 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 как класс и не нашел встроенный класс Bar в классе Foo. Он также не смог найти пространство имен, называемое Foo.Bar. Он не смог найти класс Bar в пространстве имен Foo. Точки в пространстве имен НЕ являются синтаксическими. Вся строка - это токен, а не слова, разделенные точками.

Это поведение было продемонстрировано в VS 2015, запущенном .Net 4.6

Ответ 6

Старый пост, но здесь я иду с другой идеей, которая может кому-то помочь:

"... но, похоже, единственный способ сделать это - сделать все остальные классы внутренними классами Scenegraph в файле Scenegraph.cs, и это слишком громоздко".

Это действительно лучшая реализация для множества сценариев. Но я согласен, что весь этот код в одном и том же файле .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
        }
    }
}

Я действительно думаю, что это ближе к чистой реализации внутренних классов без необходимости загромождать все в одном огромном и грязном файле.

Ответ 7

Как уже говорили другие, не рекомендуется называть класс так же, как его пространство имен.

Вот некоторые дополнительные предложения по именованию из ответа svick на связанный вопрос "Одинаковый класс и имя пространства имен" на бирже разработки программного обеспечения:

Вы правы в том, что вы не должны называть пространство имен так же, как тип, который оно содержит. Я думаю, что есть несколько подходов, которые вы можете использовать:

  • Pluralize: Model.DataSources.DataSource

Это особенно хорошо работает, если основная цель пространства имен состоит в том, чтобы содержать типы, которые наследуются от одного базового типа или реализуют один и тот же интерфейс.

  • Сократить: Model.QueryStorage

Если пространство имен содержит только небольшое количество типов, возможно, вам вообще не нужно это пространство имен.

  • Сделайте предприятие: Model.ProjectSystem.Project

Это может работать особенно для функций, которые являются важной частью вашего продукта, поэтому они заслуживают своего собственного имени.

(Обратите внимание, что в приведенном выше ответе в качестве примеров используются Model.DataSource.DataSource, Model.QueryStorage.QueryStorage. И Model.Project.Project а не MyLib.Scenegraph.Scenegraph.)

(Я также нашел другие предложения по именованию в других ответах здесь полезными.)