假设我有一个“应用程序”类。为了初始化,它需要在构造函数中进行某些设置。我们还假设设置的数量太多,以至于将它们放在自己的类中是很有吸引力的。
比较此场景的以下两种实现方式。
实施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上说嵌套类只有在外部世界不可见的情况下才是合理的。也就是说,它们仅用于包含类的内部实现。通常引用的异议是包含类的源文件的大小膨胀,但是部分类是解决该问题的完美解决方案。
我的问题是,为什么我们对嵌套类的“公开暴露”使用持谨慎态度?还有其他反对这种用法的论据吗?
答案 0 :(得分:22)
我认为没关系。这基本上是构建器模式,并且使用嵌套类非常有效。它还允许构建器访问外部类的私有成员,这非常有用。例如,您可以在构建器上使用Build方法,该方法在外部类上调用私有构造函数,该构造函数接受构建器的实例:
public class Outer
{
private Outer(Builder builder)
{
// Copy stuff
}
public class Builder
{
public Outer Build()
{
return new Outer(this);
}
}
}
这确保构建外部类实例的 only 方式是通过构建器。
我在Protocol Buffers的C#端口中使用了非常类似的模式。
答案 1 :(得分: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
。
你知道那晚会怎么睡觉?
答案 2 :(得分:0)
您可能想查看有关该主题的Microsoft has to say内容。基本上这是我所说的风格问题。
答案 3 :(得分:0)
我主要使用嵌套类来微调对嵌套和/或容器类的访问。
要记住的一点是,嵌套类定义基本上是一个类成员,并且可以访问所有容器的私有变量。
您也可以使用它来控制特定类的使用。
示例:
public abstract class Outer
{
protected class Inner
{
}
}
现在,在这种情况下,用户(您的类)只能访问Inner类,如果他实现了Outer。
答案 4 :(得分: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属性是公开的。
答案 5 :(得分:0)
我不知道这是否被认为是错误的设计,但是我在用户调用Run()方法的地方创建了一些搜索类,并传入了一个包含搜索条件的对象。然后,它返回搜索结果对象的集合。
除了将SearchCriteria和SearchResult类与Search类一起使用之外,它们没有任何实用程序。因此,我将它们嵌套在Search类下以显示它们在一起。
我必须公开嵌套类,以便Search类的客户端可以使SearchCriteria传递到Search类中,以便他们可以获取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);
}
}