如果我在运行之前就知道元素数量,应该选择什么?
Resharper 给了我 IEnumerable<string>
而不是 string[]
?
如果我在运行之前就知道元素数量,应该选择什么?
Resharper 给了我 IEnumerable<string>
而不是 string[]
?
IEnumerable<string>
,如果您仅使用IEnumerable定义的方法。这样做是因为,由于您显然不需要将值作为数组进行类型化,您可能希望将确切类型隐藏在(即使用)该值的代码的消费者(即消费者)之前,因为您可能希望在将来更改类型。IEnumerable<string>
,那么这意味着您只使用了该接口的功能,而没有使用任何数组特定的功能。按照ReSharper的建议进行更改。IEnumerable<string> sequence = new string[5]...
特别是如果它是像static readonly这样的内容,那么您应该将其设置为ReadOnlyCollection,以便条目不可修改。如果您试图将此方法作为其他方法的接口提供,则我更喜欢使您的方法输出更加通用,因此会选择 IEnumerable<string>
。
在方法内部,如果您正在尝试实例化并且不会传递到其他方法,则我会选择 string[]
。尽管我不需要 延迟执行,但在这种情况下使用哪种都无所谓。
string[]
和 IEnumerable<string>
对延迟执行没有影响。 - Mark Sowulstring[]
、List<string>
或许多其他类型都_实现了_IEnumerable<string>
。对于这样的类型,您总是会得到延迟执行,因此您声称声明不同类型对延迟执行有任何影响是错误的。 - Domenic使用 string[],你可以通过索引访问项目;而使用 IEnumerable,你需要循环查找特定索引。
IEnumerable<>
不是一种实现,而是一种接口。你可以将变量声明为IEnumerable<string>
并用string[]
构建它,因为字符串数组实现了IEnumerable<string>
。IEnumerable<string>
的内容(无论实现方式是List<string>
、string[]
还是其他任何东西)都可以使用你的字符串数组,而不必担心你传递的具体实现。只要满足接口,它就是正确类型的多态。ReSharper 可能会为您标记它,因为您没有返回最不受限制的类型。如果您将来不打算使用索引访问它,我建议使用 IEnumerable
,以减少返回它的方法的约束。
这取决于您以后的使用。如果您需要枚举这些元素,或者以后需要对它们进行排序或比较,则建议使用IEnumerable,否则使用数组。
我为一个类似的关于数组或IEnumerable用于返回值的问题撰写了这个回答,但在我发布之前它就被关闭了。我认为这个答案可能对一些人有趣,所以在这里发布。
IEnumerable相对于T[]的主要优点是,IEnumerable(用于返回值)可以变成惰性。也就是说,在需要下一个元素时才计算它。
考虑一下Directory.GetFiles和Directory.EnumerateFiles之间的区别。GetFiles返回一个数组,而EnumerateFiles返回IEnumerable。这意味着对于一个有两百万个文件的目录,数组将包含两百万个字符串。而EnumerateFiles只在需要时实例化字符串,节省了内存并提高了响应时间。
然而,并不是所有都是好处。
foreach在非数组上显着不够有效(通过反汇编ILCode可以看到这一点)。
Array承诺更多,即其长度不会改变。
惰性求值并不总是更好,考虑Directory类。GetFiles实现将打开一个查找文件句柄,迭代所有文件,关闭查找文件句柄,然后返回结果。EnumerateFiles将什么也不做,直到请求第一个查找文件,然后打开查找文件句柄并迭代文件,在枚举器被处理时关闭查找文件句柄。这意味着查找文件句柄的生命周期由调用者控制,而不是被调用者控制。可以看作是封装性较差,并且可能会在锁定文件句柄时产生潜在的运行时错误。
在我看来,我认为R#过于热衷于建议使用IEnumerable而不是数组,特别是对于返回值(输入参数具有较少的潜在缺点)。当我看到返回IEnumerable的函数时,我倾向于使用.ToArray以避免潜在的惰性求值问题,但如果集合已经是数组,则这种方法效率低下。
我喜欢这个原则:承诺很多,要求很少。即不要求输入参数必须是数组(使用IEnumerable),但是返回Array而不是IEnumerable,因为Array是一个更大的承诺。