我正在尝试理解C#中的嵌套类。我知道嵌套类是在另一个类内部定义的类,但我不明白为什么会需要这样做。
我正在尝试理解C#中的嵌套类。我知道嵌套类是在另一个类内部定义的类,但我不明白为什么会需要这样做。
我特别喜欢的一种模式是将嵌套类与工厂模式结合使用:
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对象中运行的所有代码。而且我的所有子类都可以通过基类共享实现细节。
嵌套类的目的通常只是为了限制其作用域。与普通类相比,嵌套类有额外的可能性,即使用private
修饰符(当然还有protected
)。
基本上,如果您只需要从“父”类(在作用域方面)中使用此类,则通常将其定义为嵌套类会更合适。如果这个类可能需要被在程序集/库之外使用,那么通常更方便用户将其定义为一个单独的(同级)类,无论这两个类之间是否存在任何概念上的关系。尽管从技术上讲,在public
父类中嵌套创建一个public
类是可行的,但在我看来,这很少是一个合适的实现方法。
System.Windows.Forms.ListView
的嵌套类! - Mehrdad Afshari嵌套类可以有 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);
}
}
我不明白为什么我需要这样做。
我认为你永远不需要这样做。例如,有一个像这样的嵌套类...
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作为内部/嵌套类有两个优点:
当我说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的回复中看到一个示例。
protected
)。例如,外部类可能是某种容器,而嵌套类可能是该容器的迭代器:迭代器希望访问容器的成员数据/实现细节。 - ChrisW公共嵌套成员也有很好的用处...
嵌套类可以访问外部类的私有成员。因此,当创建一个比较器(即实现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);
}
}
}
FirstNameComparer
类应该是静态的,以及 Compare
方法。 - ErikE有时候实现一个接口并从类中返回这个接口是很有用的,但这个接口的实现应该完全对外部隐藏。
比如,在C#引入yield之前,实现枚举器的一种方式就是将枚举器的实现作为集合内部的一个私有类。这样可以方便地访问集合的成员,但外部世界不需要/看到它的具体实现细节。
嵌套类非常有用,可以用于实现不应暴露的内部细节。如果您使用反射器检查像Dictionary<Tkey,TValue>或Hashtable这样的类,您会发现一些示例。
// ORIGINAL
class ImageCacheSettings { }
class ImageCacheEntry { }
class ImageCache
{
ImageCacheSettings mSettings;
List<ImageCacheEntry> mEntries;
}
并且:
// REFACTORED
class ImageCache
{
Settings mSettings;
List<Entry> mEntries;
class Settings {}
class Entry {}
}
注意:我没有考虑应该应用哪些访问修饰符(private、protected、public、internal)
public Settings Settings { get; set; }
的约定将被忽略。 - Dan Lugg