“是否有公共”嵌套类

问题描述 投票:17回答:6

假设我有一个类'Application'。为了进行初始化,需要在构造函数中进行某些设置。我们还假设设置的数量太多,以至于必须将它们放在自己的类中。

比较此方案的以下两个实现。

实施1:

class Application 
{
   Application(ApplicationSettings settings) 
   {
       //Do initialisation here
   }
}

class ApplicationSettings 
{
   //Settings related methods and properties here
}

实施2:

class Application 
{
   Application(Application.Settings settings) 
   {
       //Do initialisation here
   }

   class Settings 
   {
      //Settings related methods and properties here
   }
}

对我来说,第二种方法非常可取。它更具可读性,因为它强烈强调了两个类之间的关系。当我编写代码以在任何地方实例化Application类时,第二种方法看起来会更漂亮。

现在,请想象设置类本身又具有一些类似的“相关”类,而该类也是如此。只走三个这样的级别,在“非嵌套”情况下,班级命名就变得一发不可收拾。但是,如果您筑巢,事情仍然会保持优雅。

尽管有上文,我已经读过一些人在StackOverflow上说,嵌套类只有在外界看不到时才是合理的;也就是说,如果它们仅用于包含类的内部实现。经常被引用的反对意见是使包含类的源文件的大小过大,但是部分类是解决该问题的完美解决方案。

我的问题是,为什么我们对嵌套类的“公开暴露”使用保持警惕?还有其他反对这种使用的论点吗?

c# class-design nested-class
6个回答
23
投票

我认为很好。这基本上是构建器模式,使用嵌套类效果很好。它还允许构建器访问外部类的私有成员,这可能非常有用。例如,您可以在构建器上使用Build方法,该方法在外部类上调用私有构造器,该类使用构建器的实例:

public class Outer
{
    private Outer(Builder builder)
    {
        // Copy stuff
    }

    public class Builder
    {
        public Outer Build()
        {
            return new Outer(this);
        }
    }
}

这确保通过构造器构建外部类实例的only方法。

我在协议缓冲区的C#端口中使用了非常类似的模式。


5
投票

您可以使用名称空间来关联...相关的事物。

例如:

namespace Diner
{
    public class Sandwich
    {
        public Sandwich(Filling filling) { }
    }

    public class Filling { }
}

与将类当作名称空间使用类相比,这样做的优势在于,您可以选择在调用方使用using来简化内容:

using Diner;

...

var sandwich = new Sandwich(new Filling());

如果将Sandwich类当作Filling的命名空间使用,则必须使用全名Sandwich.Filling来引用Filling

知道了,你晚上怎么睡觉?


0
投票

您可能想查看有关该主题的什么Microsoft has to say。基本上,这是我要说的风格问题。


0
投票

当我使用带有IEnumerable属性的viewmodel时,可以有效地使用公共嵌套类的另一个实际示例是MVC模式。例如:

public class OrderViewModel
{
public int OrderId{ get; set; }
public IEnumerable<Product> Products{ get; set; }

public class Product {
public string ProductName{ get; set; }
public decimal ProductPrice{ get; set; }
}

}

我使用它是因为我不希望在外部重用Product类,因为它仅针对包含它的特定视图模型进行了自定义。但是我不能将其设为私有,因为Products属性是公开的。


0
投票

我主要使用嵌套类来微调对嵌套类和/或容器类的访问。

要记住的一件事是,嵌套的类定义基本上是一个类成员,并且可以访问所有容器的私有变量。

您还可以使用它来控制特定类的使用。

示例:

public abstract class Outer
{
  protected class Inner
  {
  }
}

现在,在这种情况下,(您班级的)用户只能访问Inner类(如果实现了Outer。)>


0
投票

我不知道这是否被认为是错误的设计,但是我在用户调用Run()方法的地方创建了一些搜索类,并传入了一个包含搜索条件的对象。然后,它返回搜索结果对象的集合。

© www.soinside.com 2019 - 2024. All rights reserved.