네임 스페이스로 정적 클래스 사용


21

정적 클래스를 네임 스페이스로 사용하는 다른 개발자를 보았습니다.

public static class CategoryA
{
    public class Item1
    {
        public void DoSomething() { }
    }
    public class Item2
    {
        public void DoSomething() { }
    }
}

public static class CategoryB
{
    public class Item3
    {
        public void DoSomething() { }
    }
    public class Item4
    {
        public void DoSomething() { }
    }
}

내부 클래스를 인스턴스화하려면 다음과 같이 보입니다.

CategoryA.Item1 item = new CategoryA.Item1();

근거는 "using"키워드를 사용하여 네임 스페이스를 숨길 수 있다는 것입니다. 그러나 정적 클래스를 사용하여 외부 계층 클래스 이름을 지정해야 네임 스페이스를 효과적으로 보존 할 수 있습니다.

Microsoft 는 지침따라이를 권장하지 않습니다 . 나는 개인적으로 그것이 가독성에 영향을 준다고 생각합니다. 당신의 생각은 무엇입니까?


1
구현에 존재하는 네임 스페이스가 필요한지 여부는 구현 자에게 달려 있습니다. 왜 네임 스페이스 (및 가짜 네임 스페이스)를 사용하게됩니까?
Craige

그룹화 목적 일 수 있습니까? 많은 하위 클래스가 있고 하위 클래스를 정적 ​​클래스로 그룹화하는 것처럼. 그게 긴장을 분명히 하는가?
user394128

하위 클래스를 하위 네임 스페이스에 배치해도 의도가 명확하지 않습니까? 또한 이것은 문서로 해결 된 문제 유형입니다.
Craige

답변:


16

네임 스페이스로 정적 클래스를 사용하면 네임 스페이스를 갖는 목적이 무시됩니다.

주요 차이점은 다음과 같습니다.

당신이 정의하는 경우 CategoryA, CategoryB<네임 스페이스로, 그리고 응용 프로그램이 두 개의 네임 스페이스를 사용하는 경우 :

CategoryA::Item1 item = new CategoryA::Item1(); 
CategoryB::Item1 item = new CategoryB::Item1();

여기 경우 CategoryA또는 CategoryB정적 클래스가 아닌 네임 스페이스, 응용 프로그램의 사용은 상기 한 바와 같이 거의 동일합니다.

그러나 네임 스페이스로 정의하고 응용 프로그램이 1 개의 네임 스페이스 만 사용하면 (포함하지 않음 CategoryB)이 경우 응용 프로그램은 실제로 다음을 사용할 수 있습니다

using namespace CategoryA; 
Item1 item = new Item1(); 

그러나 CategoryA정적 클래스로 정의했으면 위의 내용은 정의되지 않았습니다! CategoryA.something매번 글을 써야 합니다.

네임 스페이스는 이름 충돌을 피하기 위해 사용해야하지만 클래스 그룹화는 시스템 모델과 관련이있을 때 클래스 계층 구조를 사용해야합니다.


또한 누군가가 네임 스페이스를 사용하지 않으려는 경우 클래스를 사용하더라도 다음을 수행 할 수 있습니다. using Item1 = CategoryA.Item1(네임 스페이스와 마찬가지로 중첩 클래스에서도 작동한다고 생각합니다)
George Duckett

1
C ++에서 ADL 은 클래스 범위에서 작동하지 않습니다. 네임 스페이스 범위와 함께 작동합니다. 따라서 C ++에서 네임 스페이스는 자연스러운 선택 일뿐만 아니라 정확 하고 관용적 인 선택 이기도 합니다.
Nawaz

using 키워드로 네임 스페이스를 숨기지 않는 것이 OP의 의도라고 생각합니다. 그는 사용자가 매번이를 작성하도록 강요하기를 원합니다. 아마 그의 네임 스페이스는var s = new HideMe.MyPhoneNumberIs12345678.TheRealUsefulClass()
Gqqnbig

5

여기서 무슨 일이 일어나고 있는지는 관용적 인 C # 코드가 아닙니다.

어쩌면 이러한 다른 사람들이 모듈 패턴을 구현하려고 할 것입니다-이것은 함수, 액션 등뿐만 아니라 '네임 스페이스'의 클래스 (이 경우 정적 클래스)를 가질 수 있습니까?


동의합니다. 이상해 보입니다.
marko

4

우선, 모든 클래스는 네임 스페이스에 있어야하므로 예제는 실제로 다음과 같습니다.

SomeNamespace.CategoryA.Item1 item = new SomeNamespace.CategoryA.Item1();

즉, 이러한 네임 스페이스를 정의 할 수있을 때 이런 종류의 코드 체조의 이점은 없습니다.

namespace SomeNamespace.CategoryA { ... }

언젠가 상위 클래스 레벨에 정적 메소드를 저장하려고 생각하는 경우 이것이 의미가 있지만 C # 작성자가 생각한 것이 아니며 다른 사람들이 읽을 수 없게 만들 수 있습니다. 많은 시간을 낭비 할 것입니다 왜 당신이 이것을했는지 생각하고, 설명을 제공 할 소스 파일이 없는지 생각합니다.


그렇다면 왜 열거 형 이 규칙에 예외 입니까?
sq33G

그것은 다른 질문입니다 :) 그러나 열거 형을 정의하기 위해 정적 클래스를 정의하지는 않습니다.
zmilojko

1

Java, JavaScript 및 .NET 관련 네임 스페이스는 완전하지 않으며 클래스 만 저장할 수 있지만 상수 또는 전역 메서드와 같은 다른 항목은 저장할 수 없습니다.

많은 개발자들이 일부 사람들이 권장하지 않더라도 "정적 클래스"또는 "정적 메소드"트릭을 사용합니다.


0

나는 이것이 오래된 질문이라는 것을 알고 있지만 클래스를 네임 스페이스 (정적하지 않은 클래스)로 사용하는 매우 유효한 이유 중 하나는 C #이 매개 변수 또는 일반 네임 스페이스의 정의를 지원하지 않기 때문입니다. 이 주제에 대한 블로그 게시물을 작성했습니다 : http://tyreejackson.com/generics-net-part5-generic-namespaces/ .

핵심은, 상용구를 사용하여 거대한 상용구 코드를 추출 할 때 관련 클래스와 인터페이스간에 여러 일반 매개 변수를 공유해야하는 경우가 있습니다. 이를 수행하는 일반적인 방법은 각 인터페이스 및 클래스 서명에서 일반 매개 변수, 제한 조건 및 모두를 재정의하는 것입니다. 시간이 지남에 따라 매개 변수 및 제약 조건이 확산되어 유형 매개 변수를 한 유형에서 관련 유형의 유형 인수로 전달하여 관련 유형을 지속적으로 규정 할 필요는 없습니다.

외부 Generic 클래스를 사용하고 관련 유형을 중첩하면 코드를 극적으로 건조시키고 추상화를 단순화 할 수 있습니다. 그런 다음 모든 구체적인 세부 사항을 제공하는 구체적인 구현으로 파라 메트릭 네임 스페이스 클래스를 파생시킬 수 있습니다.

다음은 간단한 예입니다.

public  class   Entity
                <
                    TEntity, 
                    TDataObject, 
                    TDataObjectList, 
                    TIBusiness, 
                    TIDataAccess, 
                    TIdKey
                >
        where   TEntity         : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>, subclassed
        where   TDataObject     : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>.BaseDataObject, subclassed
        where   TDataObjectList : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>.BaseDataObjectList, subclassed
        where   TIBusiness      : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>.IBaseBusiness
        where   TIDataAccess    : Entity<TEntity, TDataObject, TDataObjectList, TIBusiness, TIDataAccess, TIdKey>.IBaseDataAccess
{

    public class    BaseDataObject
    {
        public TIdKey Id { get; set; }
    }

    public class BaseDataObjectList : Collection<TDataObject> {}

    public interface IBaseBusiness
    {

        TDataObject     LoadById(TIdKey id);
        TDataObjectList LoadAll();
        void            Save(TDataObject item);
        void            Save(TDataObjectList items);
        void            DeleteById(TIdKey id);
        bool            Validate(TDataObject item);
        bool            Validate(TDataObjectList items);

    }

    public interface IBaseDataAccess
    {

        TDataObject     LoadById(TIdKey id);
        TDataObjectList LoadAll();
        void            Save(TDataObject item);
        void            Save(TDataObjectList items);
        void            DeleteById(TIdKey id);

    }

}

이런 식으로 사용 :

public  class   User 
:
                Entity
                <
                    User, 
                    User.DataObject, 
                    User.DataObjectList, 
                    User.IBusiness, 
                    User.IDataAccess, 
                    Guid
                >
{
    public class DataObject : BaseDataObject
    {
        public string FirstName { get; set; }
        public string LastName { get; set; }
    }

    public class DataObjectList : BaseDataObjectList {}

    public interface IBusiness : IBaseBusiness
    {
        void DeactivateUserById(Guid id);
    }

    public interface IDataAcccess : IBaseDataAccess {}
}

다음과 같은 파생 상품을 사용하십시오.

public class EntityConsumer
{
    private User.IBusiness       userBusiness;
    private Permission.IBusiness permissionBusiness;

    public EntityConsumer(User.IBusiness userBusiness, Permission.IBusiness permissionBusiness) { /* assign dependencies */ }

    public void ConsumeEntities()
    {
        var users       = new User.DataObjectList();
        var permissions = this.permissionBusiness.LoadAll();

        users.Add
        (new User.DataObject()
        {
            // Assign property values
        });

        this.userBusiness.Save(users);

    }
}

이런 식으로 형식을 작성하면 형식 안전성이 추가되고 추상 클래스에서 형식이 덜 캐스팅됩니다. 그것은 더 큰 규모 에서 ArrayListvs List<T>에 해당 합니다.

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