在C#中返回IList <t> vs Array </t>

时间:2009-05-02 23:32:51

标签: c# .net arrays list mutability

我最近问某人为什么他更喜欢在IList上返回一个强类型数组。我一直认为,当面对一个具有长寿命的项目时,针对接口的编程是最灵活和最好的方式。所以当他回答时,我很奇怪:

  

我们通常更喜欢不可变类型   在可变的。数组是   不可改变的。 IList不是。

我不完全确定我理解这句话。任何人都可以帮忙澄清一下吗?

感谢您提供任何帮助。

11 个答案:

答案 0 :(得分:13)

无论是谁“他”,都是100%错误的话题。数组是非常可变的。这实际上是不返回数组的原因之一。没有办法阻止调用者将数组的元素更改为他们喜欢的任何内容。

Arrray不可变的唯一方法就是它的长度。分配数组后,其长度无法更改。甚至像Array.Resize这样的API也不会实际调整数组大小,它们只是分配一个新数组,复制内容并返回新数组(在这种情况下通过引用)。

我确实同意在很多情况下最好返回不可变数据。主要的一点是,它允许您返回对类的内部集合的引用,而无需执行完整的副本,同时防止调用者弄乱您的内部状态。大多数可变集合都无法做出这样的保证。

答案 1 :(得分:10)

我认为他可能会认为,因为数组的长度属性是不可变的,然后某种数组更多不可变而不是IList,或者他使用了错误的单词并且用不可变的方式交换了具体的。谁知道,但这是一个奇怪的答案。

我认为返回一个List有一些暗示可以修改它或者它可能会改变而返回一个数组并不意味着那么多。

例如,如果你在一个存储库顶部有一个对象模型,并且有一个像GetCars()这样的方法返回了一个List,一个初级程序员看到了cars.Add(Car c)......你认为他是完全的吗?思考cars.Add(新Car())实际上可能会将汽车添加到存储库?数组本质上更明确。

我认为列表用法更适合于属性,例如Page.Controls.Add

由于多种原因,我更喜欢返回比List更频繁的数组。

  • 习惯。收藏于1.0 / 1.1 SUCKED

  • 我更喜欢我的方法返回最简单的&amp;最轻量级的物体。如果我需要将一个数组创建一个列表,这是微不足道的。

  • 它们可以在.net 1.1中使用,如果我需要支持旧版本的运行时,它可以减少重构的表面我可以重用至少一些代码或应用相同的对象模型。< / p>

答案 2 :(得分:9)

我总是喜欢ReadOnlyCollection。列表的所有优点,但只读。

答案 3 :(得分:7)

他本可以指出的一点是IList包含Insert,Remove和Add方法,因此可以修改集合本身。另一方面,T []不能添加元素。

我应该补充一点,FxCop建议改为返回ReadOnlyCollection。索引器是只读的,因此您无法更改元素,Add和其他此类方法都会抛出NotSupportedException。

答案 4 :(得分:5)

原则上他是对的,但他不知道如何正确地练习......

  

我们通常更喜欢不可变类型   可变的。

这是正确的。

可以更好地使用不可变类型
  

数组是不可变的。 IList不是。

这是不正确的。这些都不是一成不变的。

如果要返回不可变的集合,请返回IEnumerable<T>ReadOnlyCollection<T>(使用List<T>.AsReadOnly方法)。如果它们本身不是不可变的,那些仍然不能保护它们。虽然你只能从集合中读取,但如果它们允许,你仍然可以更改每个对象中的数据。

此外,您应该考虑要返回的集合的“所有权”。如果您只是为了返回它而创建一个数组,那么没有理由不对它进行完全控制。另一方面,如果你正在返回一个属于该类成员的集合,那么你应该只允许对它进行必要的访问。

答案 5 :(得分:2)

我也不明白。除了它们的大小,数组是非常可变的。单个元素仍然可以修改。也许他的意思是数组是值类型,列表是引用类型。我不知道。

无论如何,你应该看一下Eric Lippert's opinion这个主题。也可以为你提供一些弹药供你讨论。

答案 6 :(得分:1)

也许这个人不知道他在说什么?

答案 7 :(得分:1)

将Interface作为返回类型而不是实际类型本身的原因是隐藏调用者的内部实现。这允许实现更改实际类型,而不会重新应用到应用程序的其余部分。

将内部使用的集合复制到数组以供外部使用没有任何意义,除了可变或不可变之外没有其他原因。

单独的问题是: - 返回强类型数据列表。 IList或IList。 始终首选使用强类型数据。 - 可变或不可变。 ICollection,IList或IEnumerator 返回您想要允许的数据。对于只读列表,只返回一个IEnumerator。如果允许调用者修改集合,请使用ICollection或IList。

答案 8 :(得分:0)

基本上他说“我们更喜欢在运行时不易改变的结构,因为我们认为它们不容易出错。”在这种情况下,这是否正确是另一个问题。

答案 9 :(得分:0)

也许他认为数组的大小是“不可变的”? 基本上,你宣布一次大小,你就会坚持下去。使用列表,您始终可以使用“添加”。

假设 如果确定关于列表的大小,或许数组更快一点?

答案 10 :(得分:0)

好。 IList是可变的,因为您可以添加和删除项目,而不仅仅是更改已经存在的项目。数组允许您混淆单个项目,但特定索引永远不会完全无效。有许多理由喜欢不变性 - 例如,它会使意外数据损坏的表面区域小得多。