凯瑟琳*多拉德最近的博客, 她提出了一个有趣的理由使用嵌套的课程。网。然而,她还提到,FxCop不喜欢套课程。我假设,人们的写作FxCop规则不是愚蠢,因此必须有理由这一立场,但我没有能够找到它。

有帮助吗?

解决方案

使用嵌套级上课的时候你是嵌套是唯一有用的封闭类。例如,课程的嵌套能让你写的东西像(简化):

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

你可以做一个完整的定义类在一个地方,你没有跳过任何PIMPL篮球的定义如何类工作,与外部世界不需要什么都看不见你的实施。

如果树节点类是外部的,你要么必须使所有的领域 public 或者让一堆 get/set 方法的使用它。外面的世界将会有另一类污染他们的智能感知。

其他提示

从太阳的Java教程:

为什么使用嵌套的课?有几个令人信服的理由对于使用嵌套的课程,其中包括:

  • 它是一种在逻辑上分组的课程,这些课程只用于一个地方。
  • 它增加了封装。
  • 嵌套课程可导致更易读和易于维护的代码。

逻辑分组类(如果一类是有用的唯一一个其他类,那么它是合乎逻辑的嵌入它在那类和保持两个在一起。筑巢的这种"辅助课程",使他们的软件包的更加精简。

增加的封装—考虑两个顶级课程,A和B,B需要访问的成员,否则将被宣布为私有。通过隐藏B类内一级,成员国可以声明的私人和B可以对它们进行访问。此外,B本身可以被隐藏在外面的世界。 <-这不适用于C#'s执行情况的嵌套的课程,这只适用于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

它取决于使用。我很少会使用公共嵌套类,但使用嵌套的私人类所有的时间。私人嵌套类可用于分对象,目的是只能用内部的父母。这方面的一个例子是,如果一个HashTable类包含一个私人项目,以储存数据的境内只。

如果该类意味着要使用通过调用者(外),我通常喜欢使它成为一个独立独立的类。

除了其他原因,上面列出的,还有一个原因,我能想到的不仅是使用嵌套的课程,但实际上公共嵌套课程。对于那些工作与多个通用课程,共享相同的一般类型参数,能够宣布一个通用名称空间将非常有用的。不幸的是,.网(或至少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 {}

}

然后,通过使用分类的建议,由埃里克*范*布拉克尔音乐在一个较早的意见,可以分类为单独的套文件。我建议使用Visual Studio扩展喜欢巢支持的筑巢的分类文件。这允许的"空间"类文件还被用来组织的嵌套类文件夹中的文件喜欢的方式。

例如:

实体。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
{
}

实体。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;
        }

    }

}

实体。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;
        }

    }

}

实体。IBaseBusiness.cs

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

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

}

实体。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
                >
{
}

用户。数据对象.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 {}

}

用户。汇网.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

上述是一个简单的例子使用的外流作为一个通用名称空间。我已经建立"通用名称空间"的含9个或更多类型参数的过去。具有保持这些类型参数同步的九种类型,所需要知道的类型参数繁琐的,尤其是当添加一个新的参数。使用的通用名称空间使,代码远更易于管理和可读性。

如果我的理解Katheleen的文章,她建议使用嵌套类能够写SomeEntity.集合,而不是EntityCollection< SomeEntity>.在我看来,这是有争议的方式以节省一些输入。我敢肯定,在现实世界的应用程序的集会有一些差异实现,所以你会需要建立单独的类。我认为,使用类名来限制其他类范围不是一个好主意。它污染智能感知和加强之间的依赖关系课程。使用名称空间是一个标准的方式控制课程的范围。但是我发现的使用嵌套类似于@hazzen意见是可以接受的,除非你有大量的嵌套的课程,这是一个迹象的糟糕的设计。

另一种使用没有提到为课程的嵌套是分离的一般类型。例如,假如一个人想要有一些一般的家庭的静态的课程,可以采取的方法与各种数量的参数,以及与数值对于这些参数,以及产生的代表与少参数。例如,一个希望有一个静态的方法,该方法可以把一个 Action<string, int, double> 并产生一个 String<string, int> 它将呼吁所提供的动作传递3.5作为 double;一个可能也希望有一个静态的方法,它可取一个 Action<string, int, double> 并产生一个 Action<string>, 传递 7 作为 int5.3 作为 double.使用嵌套通用类别,可以安排的方法调用可以是这样的:

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实现 类集群模式 这是基于抽象的工厂的模式。

我喜欢鸟巢的例外情况是独一个类,即。那些从来不扔任何其他地方。

例如:

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