[英]Are there drawbacks to creating a class that encapsulates Generic Collection?
我的(C#3.0 .NET 3.5)应用程序的一部分需要维护几个字符串列表。 我毫不奇怪地将它们声明为List<string>
并且一切正常,这很好。
这些List
的字符串实际上(并且始终)是基金ID。 我想知道更明确的意图是否更具意图,例如:
public class FundIdList : List<string> { }
......这也有效。 从技术上还是哲学上来说,这有什么明显的缺点吗?
我将从另一个方向开始:将字符串包装到名为FundId的类/结构中。 我认为,这样做的优势大于通用列表与专用列表。
至于FundIdList,拥有这样一个类的优势类似于FundId上面的第3点:你有一个地方可以挂钩在FundIds列表上运行的方法/函数(即聚合函数)。 如果没有这样的地方,你会发现静态帮助器方法开始在整个代码中出现,或者在一些静态助手类中出现。
List <>没有虚拟或受保护的成员 - 这些类几乎不应该是子类。 此外,虽然你可能需要List<string>
的全部功能,但如果你这样做 - 是否有必要制作这样的子类?
子类化有各种缺点。 如果您将本地类型声明为FundIdList
,那么您将无法通过例如使用linq和.ToList
来分配它,因为您的类型更具体。 我看到人们决定在这些列表中需要额外的功能,然后将其添加到子类列表类中。 这是有问题的,因为List实现忽略了这些额外的位并且可能违反了你的约束 - 例如,如果你要求唯一性并声明一个新的Add方法,那么任何人(例如)通过将列表作为一个简单地(合法地)向上转换为List<string>
任何人这样输入的参数将使用默认列表Add,而不是新的Add。 您只能添加功能,永远不会删除它 - 并且没有需要子类化来利用的受保护或虚拟成员。
因此,您无法使用扩展方法添加任何功能,并且您的类型不再完全兼容,这限制了您可以对列表执行的操作。
我更喜欢声明一个包含字符串的struct FundId
,并实现有关该字符串所需的任何保证,然后使用List<FundId>
而不是List<string>
。
最后,你真的是指List<>
吗? 我看到很多人使用List<>
来处理IEnumerable<>
或plain数组更适合的事情。 在api中公开内部List
特别棘手,因为这意味着任何API用户都可以添加/删除/更改项目。 即使您首先复制列表,这样的返回值仍然会产生误导,因为人们可能希望能够添加/删除/更改项目。 如果您没有在API中公开List
,而只是将其用于内部簿记,那么声明和使用不添加任何功能的类型(仅文档)并不是那么有趣。
仅对内部使用List<>
,如果这样做,则不要将其子类化。 如果你想要一些显式的类型安全,请在结构中包装string
(不是类,因为结构在这里更有效并且具有更好的语义:在null的FundId
和空字符串之间没有混淆,并且对象相等和哈希码工作为预期结构但需要手动指定类)。 最后,如果您需要支持枚举,或者如果您还需要索引,则使用简单的ReadOnlyCollection<>
包装器来展示IEnumerable<>
,而不是让API客户端使用内部位。 如果您确实需要可变列表API, ObservableCollection<>
至少可以让您对客户端所做的更改做出反应。
我个人会把它FundId
List<string>
,或者可能创建一个包装字符串然后存储List<FundId>
的FundId
类。
List<FundId>
选项将强制执行类型更正,并允许您对FundIds
进行一些验证。
只需将其保留为List<string>
,您的变量名称就足以告诉其他人它正在存储FundID。
var fundIDList = new List<string>();
我什么时候需要继承List<T>
?
如果您对基金ID列表有特殊的操作/操作,请继承它。
public class FundIdList : List<string>
{
public void SpecialAction()
{
//can only do with a fund id list
//sorry I can't give an example :(
}
}
除非我想要某人做他们可以做的所有事情来List<string>
,而没有对FundIdList
进行任何干预,我宁愿实现IList<string>
(或者如果我不关心的话,可以实现层次结构更高层次的接口大多数接口的成员)并在适当时委托调用私有List<string>
。
如果我确实希望有人拥有这种程度的控制权,我可能只是首先给他们一个List<string>
。 据推测,你有一些东西可以确保这些字符串实际上是“基金ID”,当你公开使用继承时,你不能再保证。
实际上,这听起来(并且经常使用List<T>
)就像私有继承的自然情况一样。 唉,C#没有私有继承,所以组合是要走的路。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.