一些程序员认为传递IEnumerable<T>
参数比传递实现更好List<T>
,IEnumerable<T>
例如List<T>
.
我越是深入研究多线程开发场景,我就越开始认为这IEnumerable<T>
也不是正确的类型,我将在下面尝试解释原因。
您在枚举集合时是否收到过以下异常?
收藏已修改;枚举操作可能无法执行。(无效操作异常)
基本上造成这种情况的原因是,您在一个线程上获得了集合,而其他人在另一个线程上修改了集合。
为了规避这个问题,我养成了一个习惯,在枚举之前拍摄集合的快照,方法是将集合转换为方法内的数组,如下所示:
static void LookAtCollection(IEnumerable<int> collection)
{
foreach (int Value in collection.ToArray() /* take a snapshot by converting to an array */)
{
Thread.Sleep(ITEM_DELAY_MS);
}
}
我的问题是这个。将数组编码而不是可枚举作为一般规则不是更好吗,即使这意味着调用者现在在使用您的 API 时被迫将其集合转换为数组?
这不是更清洁,更防弹吗?(参数类型改为数组)
static void LookAtCollection(int[] collection)
{
foreach (int Value in collection)
{
Thread.Sleep(ITEM_DELAY_MS);
}
}
该数组满足可枚举和固定长度的所有要求,并且调用者知道您将在该时间点对集合的快照进行操作,这可以节省更多错误。
我现在能找到的唯一更好的选择是 IReadOnlyCollection ,它将更加防弹,因为该集合在项目内容方面也是只读的。
编辑:
@DanielPryden 提供了一个非常好的文章“数组被认为有些有害”的链接。作者的评论“我很少需要一个集合,它具有完全可变的相当矛盾的特性,同时大小固定”和“几乎在每种情况下,都有一个比大批。” 有点说服我,阵列并不像我希望的那样接近银弹,我同意风险和漏洞。我认为现在IReadOnlyCollection<T>
接口比数组IEnumerable<T>
和IReadOnlyCollection<T>
方法声明中的参数类型?还是应该允许调用者决定IEnumerable<T>
他将什么实现传递给查看集合的方法?
感谢所有的答案。我从这些回复中学到了很多。