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


当前回答

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

我觉得你根本不需要这么做。给定一个这样的嵌套类…

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成为内部/嵌套类有两个优点:

It doesn't pollute the global scope (e.g. client code which can see A doesn't know that the B class even exists) The methods of B implicitly have access to private members of A; whereas if B weren't nested inside A, B wouldn't be able to access members of A unless those members were internal or public; but then making those members internal or public would expose them to other classes too (not just B); so instead, keep those methods of A private and let B access them by declaring B as a nested class. If you know C++, this is like saying that in C# all nested classes are automatically a 'friend' of the class in which they're contained (and, that declaring a class as nested is the only way to declare friendship in C#, since C# doesn't have a friend keyword).

当我说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的回复中看到一个例子。

其他回答

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

我觉得你根本不需要这么做。给定一个这样的嵌套类…

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成为内部/嵌套类有两个优点:

It doesn't pollute the global scope (e.g. client code which can see A doesn't know that the B class even exists) The methods of B implicitly have access to private members of A; whereas if B weren't nested inside A, B wouldn't be able to access members of A unless those members were internal or public; but then making those members internal or public would expose them to other classes too (not just B); so instead, keep those methods of A private and let B access them by declaring B as a nested class. If you know C++, this is like saying that in C# all nested classes are automatically a 'friend' of the class in which they're contained (and, that declaring a class as nested is the only way to declare friendship in C#, since C# doesn't have a friend keyword).

当我说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的回复中看到一个例子。

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

// 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:我没有考虑应该应用哪些访问修饰符(私有,受保护,公共,内部)

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

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

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

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

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