由于我一直在整合Linq思维模式,我越来越倾向于通过IEnumerable
泛型类型传递集合,这似乎构成了大多数Linq操作的基础.
但是我想知道,对于IEnumerable
泛型类型的后期评估,如果这是一个好主意.使用T[]
泛型类型更有意义吗? IList
?或者是其他东西?
编辑: 以下评论非常有趣.有一件事虽然没有得到解决,但似乎是线程安全问题.例如,如果你接受IEnumerable
一个方法的参数并且它在另一个线程中被枚举,那么当该线程试图访问它时,结果可能与那些本来要传入的结果不同.更糟糕的是,试图枚举一IEnumerable
两次-我相信抛出一个异常.我们难道不应该努力使我们的方法线程安全吗?
我经历了一个绕过的阶段,T[]
长话短说,这是背后的痛苦.IEnumerable
好多了
但是我想知道,对于IEnumerable泛型类型的后期评估,如果这是一个好主意.使用T []泛型类型更有意义吗?IList的?或者是其他东西
后期评估正是为什么IEnumerable
这么好.这是一个示例工作流程:
IEnumerablefiles = FindFileNames(); IEnumerable matched = files.Where( f => f.EndsWith(".txt") ); IEnumerable contents = matched.Select( f => File.ReadAllText(f) ); bool foundContents = contents.Any( s => s.Contains("orion") );
对于不耐烦的人,这会得到一个文件名列表,过滤掉.txt
文件,然后foundContents
如果任何文本文件包含该单词,则设置为true orion
.
如果您使用IEnumerable
上述代码编写代码,则只会根据需要逐个加载每个文件.您的内存使用率非常低,如果您匹配第一个文件,则无需查看任何后续文件.这很棒.
如果你使用数组编写完全相同的代码,你最终会预先加载所有文件内容,然后才会(如果你有任何RAM)将扫描它们中的任何一个.希望这可以解释为什么懒惰列表如此优秀.
有一件事虽然没有得到解决,但似乎是线程安全问题.例如,如果你接受
IEnumerable
一个方法的参数并且它在另一个线程中被枚举,那么当该线程试图访问它时,结果可能与那些本来要传入的结果不同.更糟糕的是,试图枚举一IEnumerable
两次-我相信抛出一个异常.我们难道不应该努力使我们的方法线程安全吗?
线程安全在这里是一个巨大的红鲱鱼.
如果您使用的是数组而不是可枚举的数组,那么它看起来应该更安全,但事实并非如此.大多数情况下,当人们返回对象数组时,他们会创建一个新数组,然后将旧对象放入其中.如果你返回那个数组,那么那些原始对象就可以被修改,你最终会得到你想要避免的那种线程问题.
甲部分解决方案是不会返回原来的对象的数组,但新的或克隆对象的数组,所以其他线程不能访问原有的.这很有用,但是IEnumerable
解决方案也没有理由不这样做.一个不比另一个更安全.
在大多数情况下,您不应该T[]
在public
接口上传递arrays().有关详细信息,请参阅Eric Lippert的博客文章" Arrays被视为有害 ".
例外是采用params
数组的方法,因为它必须是一个数组.(希望将来的版本允许params IList
在方法签名中使用" ".) foo
对于internal
会员,做任何你喜欢的事; 你可以控制界面的两面.