이름이 같은 네임 스페이스와 클래스?


95

저는 라이브러리 프로젝트를 구성하고 있으며 중앙 관리자 클래스라는 이름 Scenegraph과 Scenegraph 네임 스페이스에있는 다른 클래스가 있습니다.

내가 정말로 원하는 것은 장면 그래프가 MyLib.Scenegraph되고 다른 클래스가되는 것입니다 MyLib.Scenegraph.*.하지만 그렇게하는 유일한 방법은 다른 모든 클래스를 ScenegraphScenegraph.cs 파일 의 내부 클래스로 만드는 것입니다. 너무 다루기 어렵습니다. .

대신, 나는 그것을 Mylib.Scenegraph.Scenegraphand 로 구성했는데 MyLib.Scenegraph.*, 어떤 종류의 작동하지만 Visual Studio가 클래스 또는 네임 스페이스를 참조하는지 여부에 대해 일부 조건에서 혼란스러워합니다.

이 패키지를 구성하는 좋은 방법이있어 유지 관리 할 수없는 엉망으로 내 모든 코드를한데 모으지 않고 사용자가 편리하게 사용할 수 있습니까?

답변:


111

나는 그것의 네임 스페이스와 같은 참조 클래스 이름을 권장하지 않습니다 .

프레임 워크 디자인 지침은 섹션 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가 무엇을 의미하는지 알지 못합니다. 그리고 우리가 그것을 알아낼 때까지 우리는 두 번째 Foo가 무엇을 의미하는지 알아 내려고 노력조차하지 않습니다.


6
흥미로운 점입니다. Im stil lcogitating on it. 감사. 나는 "스타일 가이드가 말한다"로 시작하는 솔직한 주장이 나에게 깊은 인상을주지 않는다. 스타일 가이드에서 부당한 허물을 많이 보았습니다. 그러나 당신은 위에서 좋은 실용적인 주장을합니다. 어쨌든 생각할 가치가 있습니다.
user430788

5
응답은 "하지 말아야 할 일"을 말합니다. 스택 사용자 중 일부는 "해야 할 일"을 찾습니다. 누구든지 Ant_222 대답을 추천 하시겠습니까?
fantastory

3
정말 막혔더라도 네임 스페이스 외부에 유형 별칭을 만들 수 있습니다. 외부 별칭은 완전히 동일한 두 개의 전체 식별자 (네임 스페이스 + 클래스 이름)가있는 경우에만 필요합니다.
Geoffrey

4
위의 모든 것은 별다른 의견입니다. 사실 때문에 당신이 그것을하지 말아야한다는 것입니다 C # 컴파일러가 오해 할 매우 분명 무슨 일인지 말에도 불구하고. 예 using Foo.Bar;를 들어 나중에 Bar bBar네임 스페이스 내부의 클래스 (또는 열거 형) 를 아주 명확하게 참조 합니다 Foo.Bar. 그렇게하지 않는 진짜 이유는 순전히 C # 컴파일러가 그것을 올바르게 이해하지 못하기 때문입니다. 이는 매우 놀랍고 불행한 일입니다. 다른 것은 털북숭이 스타일의 조언입니다.
TJ Crowder

2
이해가 안 돼요. Foo.Foo가 모호한 이유는 무엇입니까? 이 특정 경우에 Foo 네임 스페이스의 Foo 클래스를 사용하고 싶다고 컴파일러에 직접 말합니다. 아니?
GuardianX

14

네임 스페이스와 클래스에 동일한 이름을 지정하면 다른 사람들이 말한 것처럼 컴파일러를 혼동 할 수 있습니다.

그럼 어떻게 이름을 지 을까요?

네임 스페이스에 여러 클래스가있는 경우 모든 클래스를 정의하는 이름을 찾으십시오.

네임 스페이스에 클래스가 하나만 있는 경우 (따라서 동일한 이름을 지정하려는 유혹) 네임 스페이스 ClassName NS . 이것은 Microsoft가 최소한 네임 스페이스의 이름을 지정하는 방법입니다.


4
Microsoft의 이러한 네임 스페이스에 대한 예가 있습니까?
sunefred

나는 그것을 수색하고 당신에게 돌아와야합니다.
GoTo

@sunefred 검색했지만 찾을 수 없었습니다. 그러나 나는 그것을 문서에서 본 것을 확실히 기억합니다. 네임 스페이스에 단일 클래스를 갖고 싶은 경우는 많지 않은 것 같습니다.
GoTo

9

난 당신이 내가에있어 조언을 따를 것을 제안 microsoft.public.dotnet.languages.csharp사용에 MyLib.ScenegraphUtil.ScenegraphMyLib.ScenegraphUtil.*.



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 ) {
    }
}

out 매개 변수를 사용하는 대신 출력을 반환하지 않는 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
        }
    }
}

나는 이것이 하나의 거대하고 지저분한 파일 안에 모든 것을 어지럽히 지 않고도 내부 클래스를 깔끔하게 구현할 수있는 것에 더 가깝다고 생각합니다.


2

다른 사람들이 말했듯이 클래스 이름을 네임 스페이스와 동일하게 지정하지 않는 것이 좋습니다.

다음은 Software Engineering Stack Exchange의 관련 질문 "동일한 클래스 및 네임 스페이스 이름"에 대한 svick의 답변 에서 몇 가지 추가 이름 지정 제안 입니다 .

네임 스페이스에 포함 된 유형과 동일한 이름을 지정해서는 안되는 것이 맞습니다. 사용할 수있는 몇 가지 접근 방식이 있다고 생각합니다.

  • 복수화 : Model.DataSources.DataSource

이는 네임 스페이스의 주 목적이 동일한 기본 유형에서 상속되거나 동일한 인터페이스를 구현하는 유형을 포함하는 것이라면 특히 효과적입니다.

  • 단축 : Model.QueryStorage

네임 스페이스에 적은 수의 유형 만 포함 된 경우 해당 네임 스페이스가 전혀 필요하지 않을 수 있습니다.

  • 엔터프라이즈 화 : Model.ProjectSystem.Project

이것은 특히 제품의 중요한 부분 인 기능에 대해 작동 할 수 있으므로 고유 한 이름이 필요합니다.

(참고 상기 응답 용도 Model.DataSource.DataSource, Model.QueryStorage.QueryStorage.Model.Project.Project같은 예보다는 MyLib.Scenegraph.Scenegraph).

(여기에있는 다른 답변의 다른 이름 지정 제안도 도움이되는 것으로 나타났습니다.)


1

네임 스페이스의 메인 클래스 일 때 발생합니다. 따라서 네임 스페이스를 라이브러리에 넣는 것이 하나의 동기이며 네임 스페이스 이름에 'Lib'를 추가하면 문제가 사라집니다.

namespace SocketLib
{
    class Socket
    {
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.