我试图了解C#中的嵌套类。我知道嵌套类是在另一个类中定义的类,我不知道的是为什么我需要这样做。
答案 0 :(得分:254)
我特别喜欢的模式是将嵌套类与工厂模式结合起来:
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对象中运行的所有代码。我的所有子类都可以通过基类共享实现细节。
答案 1 :(得分:107)
目的通常只是限制嵌套类的范围。与普通类相比,嵌套类具有private
修饰符(当然还有protected
)的额外可能性。
基本上,如果您只需要在“父”类(就范围而言)中使用此类,那么将它定义为嵌套类通常是合适的。如果这个类可能需要在没有程序集/库的情况下从使用,那么用户通常会更方便地将其定义为单独的(同级)类,无论是否存在任何概念关系两个班级之间。尽管在技术上可以创建嵌套在public
父类中的public
类,但在我看来,这很少适合实现。
答案 2 :(得分:49)
嵌套类可以包含private
,protected
和protected internal
访问修饰符以及public
和internal
。
例如,您正在实现返回GetEnumerator()
对象的IEnumerator<T>
方法。消费者不关心对象的实际类型。他们所知道的就是它实现了这个界面。您要返回的课程没有任何直接用途。您可以将该类声明为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);
}
}
答案 3 :(得分:42)
我不知道的是为什么我需要这样做
我认为你从来没有 需要 来做这件事。给定像这样的嵌套类......
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成为内部/嵌套类有两个优点:
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的回复中看到一个例子。
答案 4 :(得分:28)
公共嵌套成员也有很好的用途......
嵌套类可以访问外部类的私有成员。因此,在创建Comparer时(即实现IComparer接口),这是正确的方式。
在这个例子中,FirstNameComparer可以访问private _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._lastName);
}
}
}
答案 5 :(得分:17)
有时候实现一个将从类中返回的接口很有用,但该接口的实现应该完全隐藏在外部世界之外。
作为示例 - 在向C#添加yield之前,实现枚举器的一种方法是将枚举器的实现作为集合中的私有类。这将提供对集合成员的轻松访问,但外部世界不需要/看到如何实现它的细节。
答案 6 :(得分:4)
嵌套类对于实现不应公开的内部细节非常有用。如果你使用Reflector检查像Dictionary&lt; Tkey,TValue&gt;这样的类。或Hashtable你会找到一些例子。
答案 7 :(得分:2)
也许这是何时使用嵌套类的一个很好的例子?
// 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:我没有考虑应该应用哪些访问修饰符(私有,受保护,公共,内部)