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


当前回答

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

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

其他回答

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

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

And:

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

    class Settings {}
    class Entry {}
}

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

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

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

嵌套类可以具有私有、受保护和受保护的内部访问修饰符以及公共和内部访问修饰符。

例如,您正在实现GetEnumerator()方法,该方法返回一个IEnumerator<T>对象。消费者不会关心对象的实际类型。他们只知道它实现了那个接口。要返回的类没有任何直接用途。你可以声明这个类为私有嵌套类,并返回它的一个实例(这实际上是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);
    }
}

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

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对象中运行的所有代码。我的所有子类都可以通过基类共享实现细节。

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

嵌套类可以访问外部类的私有成员。因此,在一个场景中,这是正确的方式将是创建一个比较器(即。实现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);
        }
    }
}