繁体   English   中英

在GetHashCode函数中创建对象不是一个好主意吗?

[英]Is it a bad idea creating an object in a GetHashCode function?

我有一个MyBase基类和大约十二个派生类。 我在代码中严重依赖访客模式。 因此,基类是访问者的抽象宿主,每个派生类都是具体的宿主。 我正在使用实现IEqualityComparer<MyBase>接口的独立比较器。 此接口中有2种方法: Boolean Equals(MyBase a, MyBase b)Int32 GetHashCode(MyBase obj) 在上述每种方法中,我都使用访问者,以将MyBase的实例解析为派生类型之一的实例。 这就是我避免处理转换的方法。 因此,访问者是一个对象,每次调用EqualsGetHashCode都需要创建该对象。 我已经读了很多关于使GetHashCode尽可能便宜的信息,所以问题将是:

考虑到性能,在GetHashCodeEquals方法中创建对象(访问者)不是一个好主意吗?

该问题假定创建新对象的成本很高。 它不是。 创建一个新对象涉及将堆指针向上移动该对象的大小,将那些字节清零,然后调用构造函数。 只要构造函数不做任何昂贵的事情,并且有足够的内存来进行分配(如果没有,GC就需要运行并且那并不便宜),这将非常快。

与创建新对象相关的“成本”是在需要收集它们时出现的。 创建更多的对象意味着您需要更频繁地收集垃圾,因此在将来某个不确定的时刻降低了代码的速度。 话虽如此,除非您要创建许多对象或非常大的对象,并且这些对象的寿命不长,否则这根本不是问题。

GetHashCode()实现应以这样的方式编写,即第一个之后的每个调用都将很快。 如果计算对象的哈希值需要构造一个新的对象,则这是一个很好的信号,表明该对象在计算完该哈希值之后可能应该缓存该哈希值,因此以后对哈希码的请求可以很快得到答复。 注意,使用标志指示是否已计算哈希码可能不值得。 取而代之的是,确定零将不是有效的哈希码值,并具有一个HashCode字段,该字段被初始化为零,但一旦计算出哈希码便被覆盖。 如果哈希码的计算方法将产生零,则替换为其他任意值。 零值和另一个值都应该只在大约1 / 4,000,000,000的时间出现,因此将该另一个值的概率加倍到1 / 2,000,000,000应该没什么大不了的。

如果您要缓存哈希码,那么它们的计算有些昂贵,那么没关系,因为它只会执行一次。 即使缓存了哈希码,也应该设法使其变得相当快,但不要太担心它。

暂无
暂无

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

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