Tho*_*que 35 .net performance clone hashset
几天前,我回答了一个关于SO 的有趣问题HashSet<T>
.一个可能的解决方案涉及克隆hashset,在我的回答中我建议做这样的事情:
HashSet<int> original = ...
HashSet<int> clone = new HashSet<int>(original);
Run Code Online (Sandbox Code Playgroud)
虽然这种方法非常简单,但我怀疑它的效率非常低:新构造函数HashSet<T>
需要单独添加原始hashset中的每个项目,并检查它是否已经存在.这显然是浪费时间:因为源集合是a ISet<T>
,所以保证不包含重复项.应该有办法利用这些知识......
理想情况下,HashSet<T>
应该实施ICloneable
,但遗憾的是并非如此.我还检查了Reflector,看看如果HashSet<T>
源集合是一个哈希集,构造函数是否做了特定的事情,但事实并非如此.它可能可以通过在私有字段上使用反射来完成,但这将是一个丑陋的黑客......
那么,有人提出了一个更有效地克隆哈希集的聪明解决方案吗?
(请注意,这个问题纯粹是理论上的,我不需要在真实的程序中这样做)
jth*_*thg 10
如果你真的想要最有效的克隆方法HashSet<T>
,你可以做以下事情(但可能以可维护性为代价)
HashSet<T>
需要复制的字段.您可能需要为每个字段递归执行此操作.Reflection.Emit
或使用表达式树来生成一个方法,该方法可以对所有字段进行必要的复制.可能需要调用其他生成的方法来复制每个字段的值.我们正在使用运行时代码生成,因为它是直接访问私有字段的唯一方法.FormatterServices.GetUninitializedObject(...)
实例化一个空对象.使用步骤2中生成的方法将原始对象复制到新的空白对象.我检查了版本4.5.2和版本4.7.2的 .NET Framework 源代码。版本 4.7.2 确实在构造函数中进行了优化,以在传入的集合类型为 HashSet 时使用一些内部克隆逻辑进行处理。您还需要将比较器传递到构造函数中才能使此逻辑正常工作。版本 4.5.2 似乎没有这种优化。
例子:
var clonedSet = new HashSet(set, set.Comparer);
Run Code Online (Sandbox Code Playgroud)