简体   繁体   English

我已经读过迭代HashSet是不好的做法。 我应该首先调用.ToList()吗?

[英]I have read that it is bad practice to iterate over a HashSet. Should I be calling .ToList() on it first?

I have a collection of items called RegisteredItems. 我有一个名为RegisteredItems的项目集合。 I do not care about the order of the items in RegisteredItems, only that they exist. 我不关心RegisteredItems中项目的顺序,只关注它们是否存在。

I perform two types of operations on RegisteredItems: 我在RegisteredItems上执行两种类型的操作:

  • Find and return item by property. 按属性查找并退货。
  • Iterate over collection and have side-effect. 迭代收集并具有副作用。

According to: When should I use the HashSet<T> type? 根据: 我什么时候应该使用HashSet <T>类型? Robert R. says, 罗伯特R.说,

"It's somewhat dangerous to iterate over a HashSet because doing so imposes an order on the items in the set. That order is not really a property of the set. You should not rely on it. If ordering of the items in a collection is important to you, that collection isn't a set." “迭代HashSet有点危险,因为这样做会对集合中的项目施加一个顺序。该顺序实际上不是集合的属性。你不应该依赖它。如果集合中的项目的排序很重要对你来说,那个系列不是一套。“

There are some scenarios where my collection would contain 50-100 items. 在某些情况下,我的收藏将包含50-100个项目。 I realize this is not a large amount of items, but I was still hoping to reap the rewards of using a HashSet instead of List. 我意识到这不是大量的项目,但我仍然希望获得使用HashSet而不是List的回报。

I have found myself looking at the following code and wondering what to do: 我发现自己正在查看以下代码并想知道该怎么做:

LayoutManager.Instance.RegisteredItems.ToList().ForEach( item => item.DoStuff() );

vs

foreach( var item in LayoutManager.Instance.RegisteredItems)
{
    item.DoStuff();
}

RegisteredItems used to return an IList<T> , but now it returns a HashSet. RegisteredItems用于返回IList<T> ,但现在它返回一个HashSet。 I felt that, if I was using HashSet for efficiency, it would be improper to cast it as a List. 我觉得,如果我使用HashSet提高效率,将它作为List进行转换是不合适的。 Yet, the above quote from Robert leaves me feeling uneasy about iterating over it, as well. 然而,Robert的上述引言让我对迭代它感到不安。

What's the right call in this scenario? 在这种情况下,正确的呼叫是什么? Thanks 谢谢

If you don't care about order, use a HashSet<>. 如果您不关心订单,请使用HashSet <>。 The quote is about using HashSet<> being dangerous when you're worried about order. 引用是关于在担心订单时使用HashSet <>是危险的。 If you run this code multiple times, and the items are operated on in different order, will you care? 如果您多次运行此代码,并且项目按不同顺序操作,您会关心吗? If not, then you're fine. 如果没有,那你就没事了。 If yes, then don't use a HashSet<>. 如果是,则不要使用HashSet <>。 Arbitrarily converting to a List first doesn't really solve the problem. 任意转换为List首先并没有真正解决问题。

And I'm not certain, but I suspect that .ToList() will iterate over the HashSet<> to do that, so, now you're walking the collection twice. 而且我不确定,但是我怀疑.ToList()会迭代HashSet <>来做到这一点,所以,现在你走了两次集合。

Don't prematurely optimize. 不要过早优化。 If you only have 100 items, just use a HashSet<> and move on. 如果您只有100个项目,只需使用HashSet <>然后继续。 If you start caring about order, change it to a List<> then and use it as a list everwhere. 如果您开始关注订单,请将其更改为List <>然后将其用作任何列表。

如果你真的不关心订单而且你知道你的hashset中没有重复(这就是你想要的),那就继续使用hashset。

In the quoted question, I think he's saying that if you iterate over a Set, you can easily trick yourself into thinking that the items are in a certain order. 在引用的问题中,我认为他说如果你迭代一个Set,你可以轻易地欺骗自己认为这些项目是按照一定的顺序。 For example, it'd be easy to treat the first iterated item differently, but you aren't guaranteed that will remain the first iterated item. 例如,以不同方式处理第一个迭代项很容易,但不保证您将保留第一个迭代项。

As long as you keep this in mind, and consider the Set unordered, iterating over it is fine. 只要你牢记这一点,并考虑Set无序,迭代就可以了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM