【问题标题】:Why can't I access the class internals of List<T> when I derive from it?为什么我从 List<T> 派生时无法访问其类内部?
【发布时间】:2010-11-18 10:29:59
【问题描述】:
class NewList<T> : List<T>

为什么我不能访问它的内部结构,如 T[] _items 等?

为什么它们不受保护,而是私有的?

我应该为此使用合成吗?

【问题讨论】:

  • 我在这里遗漏了什么吗? T[] _items 似乎是 List 的私有成员,即使没有继承也无法直接访问。组合在这里有什么帮助?

标签: c# .net inheritance list


【解决方案1】:

List&lt;T&gt; 并非设计为基类。您应该改用System.Collections.ObjectModel 中的类之一。

【讨论】:

  • 谢谢,你知道为什么 MS 不封课吗?
  • 我不知道。不过,这肯定会使情况更加清晰。
  • @Reed:是的,我认为它现在没有被密封的唯一原因是它会破坏 [假设它有意义] 派生自它的 [坏] 代码。
【解决方案2】:

它们是私有的,因为作者(Microsoft)不打算让您访问它们,可能是出于安全原因。

您应该使用组合而不是继承。让您的班级直接公开IList&lt;T&gt; 而不是List&lt;T&gt;

List&lt;T&gt; 不应该直接暴露在公共 API 中(这实际上是在设计指南中指定的)。它只能用作内部实现细节。

【讨论】:

  • 我不认为它们是“安全”原因,更像是“正确性”
  • 正确的 api 和封装的主要目标之一是一种安全形式 - 您正在保护自己的实现不受外界影响。
【解决方案3】:

为什么我不能像访问它的内部一样 T[] _items 等?

Reflector 说 _items 是私有的。下划线表示私有成员

为什么它们不受保护,但是 私人的?

对于 _items,Microsoft 提供了公共 ToArray 方法。它返回 _items。

【讨论】:

  • 谢谢。我知道这种方法,但这会对我的收藏造成巨大损失,因为由于可访问性,它会创建一个额外的收藏。
  • 它实际上返回的是底层存储还是一个副本?这是否意味着如果您修改 ToArray-ed 数组中的项目,列表的内容会发生变化?
  • 不,它是实际数组的副本。所以您的更改不会影响原件。
【解决方案4】:

这是设计使然,仅在(绝对)必要时才公开成员,以让对象始终保持正确的状态。将字段 (_items) 公开为受保护的不是一个好主意,这需要受保护的属性。在这种情况下,已经有一个公共属性(this[])

Composition 将给您更少的访问权限 - 也没有受保护的成员。

【讨论】:

    【解决方案5】:

    你不需要它。也就是说,你可以用_items 做什么而你不能用Item : T 属性做什么?他们使用索引器为您提供了对底层数组的简单功能抽象。它的重量很轻——它所做的一切都是检查边界并增加列表的版本(在 setter 上)......

    var lst = new List<int>() { 1, 2, 3, 4, 5 };
    lst[0].Dump(); // 1
    lst.Dump(); // 1, 2, 3, 4, 5
    lst[0] = 2;
    lst.Dump(); // 2, 2, 3, 4, 5
    

    【讨论】:

    • 我至少能想到两件事:(1)将列表项作为ref 参数传递给外部代码或Interlocked.CompareExchange 等方法; (2) 对于继承List&lt;someValueType&gt;的类型,访问项目的各个字段(包括修改它们或将它们作为ref参数传递)。
    猜你喜欢
    • 2017-11-29
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-11-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多