20

假设我有一个类“应用程序”。为了被初始化,它需要在构造函数中进行某些设置。让我们还假设设置的数量如此之多,以至于将它们放在自己的类中是令人信服的。

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

实施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 类时,第二种方法看起来会更漂亮。

现在想象一下,Settings 类本身又具有一些类似的“相关”类,而该类也同样如此。只进行三个这样的级别,并且在“非嵌套”情况下类命名会失控。然而,如果你嵌套,事情仍然保持优雅。

尽管如此,我还是读到有人在 StackOverflow 上说嵌套类只有在它们对外界不可见时才是合理的;也就是说,如果它们仅用于包含类的内部实现。普遍引用的反对意见是膨胀包含类的源文件的大小,但部分类是该问题的完美解决方案。

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

4

6 回答 6

27

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

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

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

这确保了构建外部类实例的唯一方法是通过构建器。

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

于 2008-12-03T13:47:31.207 回答
6

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

例如:

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.

知道这一点,你晚上怎么睡觉?

于 2008-12-03T14:01:07.857 回答
1

您可能想查看Microsoft 对此主题的看法。基本上这是我要说的风格问题。

于 2008-12-03T13:44:09.530 回答
0

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

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

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

例子:

public abstract class Outer
{
  protected class Inner
  {
  }
}

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

于 2008-12-03T13:44:42.023 回答
0

另一个有效使用公共嵌套类的实际示例是在 MVC 模式中,当我使用具有 IEnumerable 属性的视图模型时。例如:

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 属性是公开的。

于 2015-12-21T15:23:46.887 回答
-1

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

除了将它们与 Search 类一起使用之外,这些 SearchCriteria 和 SearchResult 类没有任何实用性。因此,我将它们嵌套在 Search 类下以显示它们一起使用。

我必须公开嵌套类,以便 Search 类的客户端可以将 SearchCriteria 传递给 Search 类,这样他们就可以获得搜索结果。

public class PersonSearch
{
    public PersonSearchCriteria
    {
        string FirstName {get; set;}
        string LastName {get; set;}
    }

    public PersonSearchResult
    {
        string FirstName {get;}
        string MiddleName {get;}
        string LastName {get;}
        string Quest {get;}
        string FavoriteColor {get;}
    }

    public static List<PersonSearchResult> Run(PersonSearchCriteria criteria)
    {
        // create a query using the given criteria

        // run the query

        // return the results 
    }
}


public class PersonSearchTester
{
    public void Test()
    {
        PersonSearch.PersonSearchCriteria criteria = new PersonSearch.PersonSearchCriteria();
        criteria.FirstName = "George";
        criteria.LastName  = "Washington";

        List<PersonSearch.PersonSearchResults> results = 
            PersonSearch.Run(criteria);
    }
}
于 2019-12-11T23:20:23.147 回答