我的(C#3.0 .NET 3.5)应用程序的一部分需要维护几个字符串列表。我毫不奇怪地将它们声明为List<string>
并且一切正常,这很好。
这些List
中的字符串实际上(并且始终)是基金ID。我想知道是否可能更明确地表达意图,例如:
public class FundIdList : List<string> { }
......这也有效。从技术上还是哲学上来说,这有什么明显的缺点吗?
答案 0 :(得分:7)
我将从另一个方向开始:将字符串包装到名为FundId的类/结构中。我认为,这样做的优势大于通用列表与专业列表。
至于FundIdList,拥有这样一个类的优势类似于上面的FundId第3点:你有一个地方可以挂钩在FundId列表上运行的方法/函数(即聚合函数)。如果没有这样的地方,你会发现静态辅助方法开始在整个代码中出现,或者在一些静态辅助类中。
答案 1 :(得分:3)
列表与LT;&GT;没有虚拟或受保护的成员 - 这些类几乎从不被子类化。此外,虽然你可能需要List<string>
的全部功能,但是如果你这样做的话 - 是否有必要制作这样的子类?
子类化有各种缺点。如果您将本地类型声明为FundIdList
,那么您将无法通过例如使用linq和.ToList
,因为您的类型更具体。我看到人们决定在这些列表中需要额外的功能,然后将其添加到子类列表类中。这是有问题的,因为List实现会忽略这些额外的位并可能违反您的约束 - 例如如果您要求唯一性并声明一个新的Add方法,那么通过将列表作为参数输入简单(合法地)转发到List<string>
的任何人都将使用默认列表Add,而不是新的Add。您只能添加功能,永远不会删除它 - 并且没有需要子类化的受保护或虚拟成员才能利用。
因此,您无法使用扩展方法真正添加任何功能,并且您的类型不再完全兼容,这限制了您可以对列表执行的操作。
我更喜欢声明一个包含字符串的结构FundId
,并实现有关该字符串所需的任何保证,然后使用List<FundId>
而不是List<string>
。
最后,你的意思是List<>
吗?我看到很多人使用List<>
来表示IEnumerable<>
或普通数组更适合的事情。在api中公开您的内部List
特别棘手,因为这意味着任何API用户都可以添加/删除/更改项目。即使您首先复制列表,这样的返回值仍然会产生误导,因为人们可能期望能够添加/删除/更改项目。如果你不在API中公开List
而仅仅使用它进行内部簿记,那么声明和使用不添加任何功能的类型并不是那么有趣,只有文档
仅对内部使用List<>
,如果这样做,则不要将其子类化。如果你想要一些显式的类型安全,请在结构(而不是类)中包装string
,因为结构在这里更有效并且具有更好的语义:空FundId
和空字符串之间没有混淆,对象相等性和哈希码与结构一样工作,但需要为类手动指定)。最后,如果您需要支持枚举,或者如果您还需要索引,请在您的列表周围使用简单的ReadOnlyCollection<>
包装器而不是让API客户端使用内部位来公开IEnumerable<>
。如果确实需要可变列表API,ObservableCollection<>
至少可以让您对客户端所做的更改做出反应。
答案 2 :(得分:2)
我个人会将其保留为List<string>
,或者可能创建一个包裹字符串然后存储FundId
的{{1}}类。
List<FundId>
选项会强制执行类型更正,并允许您对List<FundId>
进行一些验证。
答案 3 :(得分:1)
将其保留为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 :(
}
}
答案 4 :(得分:0)
除非我希望某人尽可能做List<string>
所做的一切,而FundIdList
没有任何干预,我宁愿实施IList<string>
(或更高的界面)层次结构,如果我不关心该接口的大多数成员)并在适当时委托调用私有List<string>
。
如果我确实希望某人拥有这种程度的控制权,我可能会首先给他们一个List<string>
。大概你有一些东西可以确保这些字符串实际上是“基金ID”,当你公开使用继承时,你不能再保证这些。
实际上,这听起来(通常与List<T>
一样)就像私有继承的自然情况一样。唉,C#没有私有继承,所以组合是要走的路。