문제

캐슬린 돌라드 소의 최신 블로그 게시물, 그녀는 선물 재미있는 이유를 사용하여 중첩된 클래스에서.net.그러나,또한 그녀는 언급 FxCop 좋아하지 않는다 중첩된 클래스입니다.나는 가정하면 사람들은 쓰기 FxCop 규칙은 멍청하지 않습니다,그래서 거기 있어야의 뒤에 추론하는 위치이다,그러나 나는 할 수 없었던 그것을 찾을 수 있습니다.

도움이 되었습니까?

해결책

사용 중첩된 클래스 경우 등 당신이 중첩에만 유용하여 바깥쪽 클래스입니다.예를 들어,중첩된 클래스를 작성할 수 있습 같은 것(간체):

public class SortedMap {
    private class TreeNode {
        TreeNode left;
        TreeNode right;
    }
}

할 수 있는 완전한 정의 클래스의 한 장소에서,당신은 뛰어올라야 하지 않을 통해 어떤 PIMPL 농구를 정의하는 방법 당신의 클래스 작품과 외부 세계를 볼 필요가 없을 경우 아무것도의 구현합니다.

는 경우 트 클래스 외부에,당신은 것 중 하나를 확인해야 모든 분야 public 거나 잔뜩 get/set 를 사용하는 방법을 알려드리겠습니다.외부 세계에 있는 또 다른 클래스는 오염시키는 자신의 컴포넌트입니다.

다른 팁

Sun's Java 튜토리얼:

을 사용하는 이유 중첩하십니까?거기에 여러 가지를 위해 강력한 이유를 사용하여 중첩된 클래스,그 중:

  • 그것의 방법을 논리적으로 그룹화하는 클래스에 사용되는 하나의 장소입니다.
  • 증가를 캡슐화합니다.
  • 중첩된 클래스로 이어질 수 있습 읽기 및 유지 관리한 코드입니다.

논리적으로 그룹화—클래스의 경우 클래스에 유용한 다른 하나의 클래스,그것은 논리적 그것을 포함에서 해당 클래스고 유지 두 가지를 함께.중첩 그러한"도우미 클래스는"자신의 패키지를 더 효율적으로 개선되었습니다.

증가된 캡슐화—고려 두 최고 수준의 수업을 A 와 B B 에 대한 액세스를 필요 구성원으로 선언 개인이다.에 의해 숨어있는 클래스 B 내에서 클래스 A,의 회원을 선언할 수 있습니다 개인 및 B 액세스할 수 있습니다.또한,B 체에서 숨길 수 있습니다. <-이 적용되지 않 C#'의 구현의 중첩된 클래스,이만 적용됩니다 Java.

더 읽,유지 관리할 수 있는 코드—중첩의 작은 클래스에서 최고 수준의 수업을 배치 코드에 가까운 곳에 그것을 사용합니다.

완벽하게 게으른 스레드에 안전한 단일 패턴

public sealed class Singleton
{
    Singleton()
    {
    }

    public static Singleton Instance
    {
        get
        {
            return Nested.instance;
        }
    }

    class Nested
    {
        // Explicit static constructor to tell C# compiler
        // not to mark type as beforefieldinit
        static Nested()
        {
        }

        internal static readonly Singleton instance = new Singleton();
    }
}

출처: http://www.yoda.arachsys.com/csharp/singleton.html

에 따라 사용합니다.나는 거의 것 사용하는 공지 중 하지만 사용하여 민간 중첩된 클래스의 모든 시간입니다.Private 중첩 등을 위해 사용될 수 있 sub-객체는 사용하기 위한 내부에서만 부모입니다.이 예제는 것은 경우 해시 테이블 등을 포함한 민간 항목을 저장할 데이터를 내부적으로만 있습니다.

클래스의 경우 사용되는 것을 의미한 발신자(외부),나는 일반적으로 같은 그것을 만드는 별도의 독립 클래스입니다.

외에 다른 이유 위에 나열된 하나의 이유가있는 나의 생각할 수 있지만 사용이 중첩된 클래스가 있지만,사실은 공공의 중첩된 클래스입니다.일하는 사람들을위한 여러 일반을 공유하는 클래스와 같은 일반적인 유형을 매개 변수는 능력을 선언하는 일반적인 네임스페이스는 것이 매우 유용합니다.불행하게도,.Net(또는 이상 C#)을 지원하지 않는 아이디어의 일반적인 네임스페이스입니다.그래서 같은 목표를 달성하기 위해,우리가 사용할 수 있습니다 일반적인 수업을 이행하는 동일한 목표입니다.다음 예에서 클래스에 관련 논리 개체:

public  class       BaseDataObject
                    <
                        tDataObject, 
                        tDataObjectList, 
                        tBusiness, 
                        tDataAccess
                    >
        where       tDataObject     : BaseDataObject<tDataObject, tDataObjectList, tBusiness, tDataAccess>
        where       tDataObjectList : BaseDataObjectList<tDataObject, tDataObjectList, tBusiness, tDataAccess>, new()
        where       tBusiness       : IBaseBusiness<tDataObject, tDataObjectList, tBusiness, tDataAccess>
        where       tDataAccess     : IBaseDataAccess<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{
}

public  class       BaseDataObjectList
                    <
                        tDataObject, 
                        tDataObjectList, 
                        tBusiness, 
                        tDataAccess
                    >
:   
                    CollectionBase<tDataObject>
        where       tDataObject     : BaseDataObject<tDataObject, tDataObjectList, tBusiness, tDataAccess>
        where       tDataObjectList : BaseDataObjectList<tDataObject, tDataObjectList, tBusiness, tDataAccess>, new()
        where       tBusiness       : IBaseBusiness<tDataObject, tDataObjectList, tBusiness, tDataAccess>
        where       tDataAccess     : IBaseDataAccess<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{
}

public  interface   IBaseBusiness
                    <
                        tDataObject, 
                        tDataObjectList, 
                        tBusiness, 
                        tDataAccess
                    >
        where       tDataObject     : BaseDataObject<tDataObject, tDataObjectList, tBusiness, tDataAccess>
        where       tDataObjectList : BaseDataObjectList<tDataObject, tDataObjectList, tBusiness, tDataAccess>, new()
        where       tBusiness       : IBaseBusiness<tDataObject, tDataObjectList, tBusiness, tDataAccess>
        where       tDataAccess     : IBaseDataAccess<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{
}

public  interface   IBaseDataAccess
                    <
                        tDataObject, 
                        tDataObjectList, 
                        tBusiness, 
                        tDataAccess
                    >
        where       tDataObject     : BaseDataObject<tDataObject, tDataObjectList, tBusiness, tDataAccess>
        where       tDataObjectList : BaseDataObjectList<tDataObject, tDataObjectList, tBusiness, tDataAccess>, new()
        where       tBusiness       : IBaseBusiness<tDataObject, tDataObjectList, tBusiness, tDataAccess>
        where       tDataAccess     : IBaseDataAccess<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{
}

우리는 우리를 단순화할 수 있습의 서명은 이러한 클래스를 사용하여 일반적인 네임스페이스(구현을 통해 중첩된 클래스):

public
partial class   Entity
                <
                    tDataObject, 
                    tDataObjectList, 
                    tBusiness, 
                    tDataAccess
                >
        where   tDataObject     : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.BaseDataObject
        where   tDataObjectList : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.BaseDataObjectList, new()
        where   tBusiness       : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.IBaseBusiness
        where   tDataAccess     : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.IBaseDataAccess
{

    public  class       BaseDataObject {}

    public  class       BaseDataObjectList : CollectionBase<tDataObject> {}

    public  interface   IBaseBusiness {}

    public  interface   IBaseDataAccess {}

}

그런 다음의 사용을 통해 부분적인 클래스에 의해 제안으로 에릭 van 브라켈에서는 이전의 의견할 수 있는 별도의 수업으로 별도의 중첩된 파일이 있습니다.내가 사용하는 것이 좋습니다 Visual Studio 확장 같은 NestIn 을 지원하는 중첩의 부분 클래스 파일이 있습니다.이것은"네임스페이스"클래스 파일을 구성하는 중요한 폴더에 파일을 같은 방법입니다.

예를 들어:

Entity.cs

public
partial class   Entity
                <
                    tDataObject, 
                    tDataObjectList, 
                    tBusiness, 
                    tDataAccess
                >
        where   tDataObject     : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.BaseDataObject
        where   tDataObjectList : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.BaseDataObjectList, new()
        where   tBusiness       : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.IBaseBusiness
        where   tDataAccess     : Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>.IBaseDataAccess
{
}

Entity.BaseDataObject.cs

partial class   Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{

    public  class   BaseDataObject
    {

        public  DataTimeOffset  CreatedDateTime     { get; set; }
        public  Guid            CreatedById         { get; set; }
        public  Guid            Id                  { get; set; }
        public  DataTimeOffset  LastUpdateDateTime  { get; set; }
        public  Guid            LastUpdatedById     { get; set; }

        public
        static
        implicit    operator    tDataObjectList(DataObject dataObject)
        {
            var returnList  = new tDataObjectList();
            returnList.Add((tDataObject) this);
            return returnList;
        }

    }

}

Entity.BaseDataObjectList.cs

partial class   Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{

    public  class   BaseDataObjectList : CollectionBase<tDataObject>
    {

        public  tDataObjectList ShallowClone() 
        {
            var returnList  = new tDataObjectList();
            returnList.AddRange(this);
            return returnList;
        }

    }

}

Entity.IBaseBusiness.cs

partial class   Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{

    public  interface   IBaseBusiness
    {
        tDataObjectList Load();
        void            Delete();
        void            Save(tDataObjectList data);
    }

}

Entity.IBaseDataAccess.cs

partial class   Entity<tDataObject, tDataObjectList, tBusiness, tDataAccess>
{

    public  interface   IBaseDataAccess
    {
        tDataObjectList Load();
        void            Delete();
        void            Save(tDataObjectList data);
    }

}

에 있는 파일을 visual studio 솔루션 탐색기의 것 다음으로 구성은:

Entity.cs
+   Entity.BaseDataObject.cs
+   Entity.BaseDataObjectList.cs
+   Entity.IBaseBusiness.cs
+   Entity.IBaseDataAccess.cs

그리고 당신을 구현하는 일반적인 네임스페이스는 다음과 같:

사용자.cs

public
partial class   User
:
                Entity
                <
                    User.DataObject, 
                    User.DataObjectList, 
                    User.IBusiness, 
                    User.IDataAccess
                >
{
}

사용자.DataObject.cs

partial class   User
{

    public  class   DataObject : BaseDataObject 
    {
        public  string  UserName            { get; set; }
        public  byte[]  PasswordHash        { get; set; }
        public  bool    AccountIsEnabled    { get; set; }
    }

}

사용자.DataObjectList.cs

partial class   User
{

    public  class   DataObjectList : BaseDataObjectList {}

}

사용자.IBusiness.cs

partial class   User
{

    public  interface   IBusiness : IBaseBusiness {}

}

사용자.IDataAccess.cs

partial class   User
{

    public  interface   IDataAccess : IBaseDataAccess {}

}

그리고 파일 구성 솔루션 탐색기에서 다음과 같다:

User.cs
+   User.DataObject.cs
+   User.DataObjectList.cs
+   User.IBusiness.cs
+   User.IDataAccess.cs

상기의 간단한 예제를 사용하여 외부로 클래스 일반적인 네임스페이스가 있습니다.I've built"일반적인"네임스페이스를 포함 9 나 이상의 입력에서 매개 변수다.을 유지하는 매개변수 유형 동기화에서 아홉는 형식을 필요한 모든 유형을 알고 매개 변수가 지루한,특히 새로운 매개 변수입니다.의 사용은 일반적인 네임스페이스에는 코드는 훨씬 더 관리하고 있습니다.

내가 이해하는 경우 Katheleen 의 문서에서는 바로,그녀는 그 제안을 사용하여 중첩된 클래스를 작성할 수 있 SomeEntity.컬렉션 대신 EntityCollection< SomeEntity>.내 생각에 그것은 논란을 저장하는 방법 당신이 일부를 입력합니다.이건에서 실제 응용 프로그램 컬렉션이 일부 차이점 구현에,그래서 당신은 것을 만들 필요가 별도의 클래스가 어쨌든.내가 생각하는 클래스를 사용하는 이름을 제한하는 다른 클래스의 범위는 좋은 생각이 아니다.그것은 오염 intellisense 고 강화하는 간의 종속성됩니다.네임스페이스를 사용하는 표준 방식으로 제어 클래스의 범위가 있습니다.그러나 내가 찾는 사용 중첩 같은 클래스에서@hazzen 의견은 허용되지 않는 한 당신의 톤이있다 중첩된 클래스의 표시가 나쁜 디자인이다.

다른 사용하지 않는 아직 언급한 중첩된 클래스의 분리는 일반적인 형식입니다.예를 들어,가정 하나를 가지고 싶어서는 몇 가지 일반적인 가족의 정체되는 클래스를 취할 수 있습 방법과 다양한 숫자의 매개 변수와 함께 값에 대한 일부 사람들의 매개변수,그리고 생성하는 대리인으로 적은 매개 변수입니다.예를 들어,하나의 소원을 정하는 방법을 취할 수 있습니다 Action<string, int, double> 과 생성 String<string, int> 는 제공된 작업 통 3.5 로 double;하나 계속하시겠습니까 수도 있습니다 정적 방법을 취할 수 있습니다인 Action<string, int, double> 과 생성 Action<string>, 전달 7int5.3double.를 사용하여 일반 중첩된 클래스,하나를 준비하는 메소드 호출이 같은 것:

MakeDelegate<string,int>.WithParams<double>(theDelegate, 3.5);
MakeDelegate<string>.WithParams<int,double>(theDelegate, 7, 5.3);

나기 때문에,후자의 형태에서 각 표현을 유추할 수 있지만 전 사람 할 수 없습니다:

MakeDelegate<string,int>.WithParams(theDelegate, 3.5);
MakeDelegate<string>.WithParams(theDelegate, 7, 5.3);

를 사용하여 중첩된 일반적인 유형은 그것을 가능하게 하는 대리인에 적용되는 부품의 전반적인 유형을 설명합니다.

중첩된 클래스를 사용할 수 있 위해 다음과 같은 요구 사항:

  1. 분류의 데이터
  2. 을 때의 논리의 주요 클래스는 복잡하고 당신은 같은 느낌을 필요로 하위를 관리할 수 있는 개체 클래스
  3. 할 때는 국가의 존재를 완전히 클래스에 따라 달라집을 감싸고 있는 클래스

내가 자주 사용하는 중첩된 클래스를 구현 숨기기 세부 사항입니다. 예를 들어서 에릭 프라의 대답은 여기:

abstract public class BankAccount
{
    private BankAccount() { }
    // Now no one else can extend BankAccount because a derived class
    // must be able to call a constructor, but all the constructors are
    // private!
    private sealed class ChequingAccount : BankAccount { ... }
    public static BankAccount MakeChequingAccount() { return new ChequingAccount(); }
    private sealed class SavingsAccount : BankAccount { ... }
}

이것은 기도와 더 나은 사용의 제네릭입니다.이 질문 두 가지 멋진 예입니다.그래서 내가 끝까지 쓰기

Equality<Person>.CreateComparer(p => p.Id);

new EqualityComparer<Person, int>(p => p.Id);

또한 내가 있을 수 있는 일반 목록 Equality<Person>EqualityComparer<Person, int>

var l = new List<Equality<Person>> 
        { 
         Equality<Person>.CreateComparer(p => p.Id),
         Equality<Person>.CreateComparer(p => p.Name) 
        }

var l = new List<EqualityComparer<Person, ??>>> 
        { 
         new EqualityComparer<Person, int>>(p => p.Id),
         new EqualityComparer<Person, string>>(p => p.Name) 
        }

이 가능하지 않습니다.그의 혜택이 중첩된 클래스를 상속하는 부모에서 클래스입니다.

또 다른 경우(의 자연이 숨어있는 구현이)때 만들고 싶은 클래스의 구성원(분야,특성 등)에 액세스할 수 있만을 위한 하나의 클래스:

public class Outer 
{
   class Inner //private class
   {
       public int Field; //public field
   }

   static inner = new Inner { Field = -1 }; // Field is accessible here, but in no other class
}

나우팔 언급된 구현의 추상적인 공장 패턴,해당 코드를 수 있습 axtended 을 달성하기 클래스는 클러스터의 패턴 기초에서 추상적 공장에 패턴이 있습니다.

내가 좋아하는 둥지를 예고 없이 수정될 수 있습니다 독특한 하나의 클래스,ie.는 사람은 결코 버리지 않았다에서 다른 장소입니다.

예를 들어:

public class MyClass
{
    void DoStuff()
    {
        if (!someArbitraryCondition)
        {
            // This is the only class from which OhNoException is thrown
            throw new OhNoException(
                "Oh no! Some arbitrary condition was not satisfied!");
        }
        // Do other stuff
    }

    public class OhNoException : Exception
    {
        // Constructors calling base()
    }
}

이것을 유지하는 데 도움이 귀하의 프로젝트 파이 깔끔하고 전체의 수백 그루터기 같은 작은 예외됩니다.

명심해야 합하여 테스트 중첩된 클래스입니다.개인 경우,당신은 할 수 없 테스트에서 격리됩니다.

당신이 그것을 만들 수 있다 내부 하지만, 와 함께 InternalsVisibleTo 특성.그러나 이 같은 것으로 만들고 프라이빗 필드를 내부에 대해서만,목적을 테스트하는 나쁜 자기 문서입니다.

그래서,당신은 할 수 있습만을 구현하는 개인 중첩된 클래스를 포함하 낮은 복잡합니다.

예를 이 경우:

class Join_Operator
{

    class Departamento
    {
        public int idDepto { get; set; }
        public string nombreDepto { get; set; }
    }

    class Empleado
    {
        public int idDepto { get; set; }
        public string nombreEmpleado { get; set; }
    }

    public void JoinTables()
    {
        List<Departamento> departamentos = new List<Departamento>();
        departamentos.Add(new Departamento { idDepto = 1, nombreDepto = "Arquitectura" });
        departamentos.Add(new Departamento { idDepto = 2, nombreDepto = "Programación" });

        List<Empleado> empleados = new List<Empleado>();
        empleados.Add(new Empleado { idDepto = 1, nombreEmpleado = "John Doe." });
        empleados.Add(new Empleado { idDepto = 2, nombreEmpleado = "Jim Bell" });

        var joinList = (from e in empleados
                        join d in departamentos on
                        e.idDepto equals d.idDepto
                        select new
                        {
                            nombreEmpleado = e.nombreEmpleado,
                            nombreDepto = d.nombreDepto
                        });
        foreach (var dato in joinList)
        {
            Console.WriteLine("{0} es empleado del departamento de {1}", dato.nombreEmpleado, dato.nombreDepto);
        }
    }
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top