为什么我需要使用c#嵌套类

我试图了解c#中的嵌套类。我理解嵌套类是在另一个类中定义的类,我不明白的是为什么我需要这样做。

194832 次浏览

其目的通常只是限制嵌套类的范围。与普通类相比,嵌套类具有额外的private修饰符(当然还有protected)的可能性。

基本上,如果您只需要从“父”类中使用这个类(就作用域而言),那么通常将其定义为嵌套类是合适的。如果这个类可能需要从没有程序集/库中使用,那么用户通常更方便地将其定义为一个单独的(兄弟)类,无论这两个类之间是否有任何概念上的关系。尽管在技术上可以在public父类中创建嵌套的public类,但在我看来,这很少是一个合适的实现。

嵌套类可以有privateprotectedprotected internal访问修饰符以及publicinternal

例如,您正在实现返回IEnumerator<T>对象的GetEnumerator()方法。消费者不会关心对象的实际类型。他们只知道它实现了那个接口。要返回的类没有任何直接用途。你可以声明这个类为private嵌套类,并返回它的一个实例(这实际上是c#编译器实现迭代器的方式):

class MyUselessList : IEnumerable<int> {
// ...
private List<int> internalList;
private class UselessListEnumerator : IEnumerator<int> {
private MyUselessList obj;
public UselessListEnumerator(MyUselessList o) {
obj = o;
}
private int currentIndex = -1;
public int Current {
get { return obj.internalList[currentIndex]; }
}
public bool MoveNext() {
return ++currentIndex < obj.internalList.Count;
}
}
public IEnumerator<int> GetEnumerator() {
return new UselessListEnumerator(this);
}
}

有时候,实现一个将从类内部返回的接口是有用的,但该接口的实现应该完全对外界隐藏。

举个例子,在将yield添加到c#之前,实现枚举器的一种方法是将枚举器的实现作为一个集合中的私有类。这将为访问集合的成员提供方便,但外部世界不需要/看到这是如何实现的细节。

嵌套类对于实现不应该公开的内部细节非常有用。如果你使用Reflector检查类,如Dictionary<Tkey,TValue>或者哈希表,你会找到一些例子。

我不明白的是我为什么要这么做

我认为你从来没有< em > < / em >需要做这个。给定一个这样的嵌套类…

class A
{
//B is used to help implement A
class B
{
...etc...
}
...etc...
}

... 你总是可以移动内部/嵌套类到全局作用域,像这样…

class A
{
...etc...
}


//B is used to help implement A
class B
{
...etc...
}

然而,当B仅用于帮助实现A时,则使B成为内部/嵌套类有两个优点:

  • 它不会污染全局作用域(例如,可以看到A的客户端代码甚至不知道B类的存在)
  • B的方法隐式地访问A的私有成员;然而,如果B不在A内嵌套,B将无法访问A的成员,除非这些成员是内部成员或公共成员;但将这些成员设置为内部成员或公开成员也会将它们暴露给其他类(不仅仅是B类);因此,保留A的那些方法为私有,让B通过声明B为嵌套类来访问它们。如果你懂c++,这就像说在c#中所有嵌套类都自动是包含它们的类的'朋友'(并且,声明一个嵌套类是在c#中声明友谊的唯一方法,因为c#没有friend关键字)。

当我说B可以访问A的私有成员时,这是假设B有一个对A的引用;它经常这样做,因为嵌套类通常是这样声明的…

class A
{
//used to help implement A
class B
{
A m_a;
internal B(A a) { m_a = a; }
...methods of B can access private members of the m_a instance...
}
...etc...
}

... 并使用这样的代码从a的方法构建…

//create an instance of B, whose implementation can access members of self
B b = new B(this);

你可以在Mehrdad的回复中看到一个例子。

公共嵌套成员也有很好的用途…

嵌套类可以访问外部类的私有成员。因此,在一个场景中,这是正确的方式将是创建一个比较器(即。实现IComparer接口)。

在这个例子中,FirstNameComparer可以访问私有的_firstName成员,如果类是一个单独的类,它就不能访问。

public class Person
{
private string _firstName;
private string _lastName;
private DateTime _birthday;


//...
    

public class FirstNameComparer : IComparer<Person>
{
public int Compare(Person x, Person y)
{
return x._firstName.CompareTo(y._firstName);
}
}
}

我特别喜欢的一个模式是将嵌套类与工厂模式结合起来:

public abstract class BankAccount
{
private BankAccount() {} // prevent third-party subclassing.
private sealed class SavingsAccount : BankAccount { ... }
private sealed class ChequingAccount : BankAccount { ... }
public static BankAccount MakeSavingAccount() { ... }
public static BankAccount MakeChequingAccount() { ... }
}

通过像这样嵌套类,我使第三方不可能创建他们自己的子类。我可以完全控制在任何bankaccount对象中运行的所有代码。我的所有子类都可以通过基类共享实现细节。

也许这是一个何时使用嵌套类的好例子?

// ORIGINAL
class ImageCacheSettings { }
class ImageCacheEntry { }
class ImageCache
{
ImageCacheSettings mSettings;
List<ImageCacheEntry> mEntries;
}

和:

// REFACTORED
class ImageCache
{
Settings mSettings;
List<Entry> mEntries;


class Settings {}
class Entry {}
}

PS:我没有考虑应该应用哪些访问修饰符(私有,受保护,公共,内部)