目录
介绍
概念化这个混乱
编码此混乱
警告
使用其他容器
有时有必要将集合用作字典键,但是这可能会导致性能下降并且不安全。以下是使它更快更安全的方法。
- 下载源4.9 KB
使用C#进行功能样式编程时,您最终可能会遇到需要按项目的有序列表来键入字典的情况。有好的方法,但不是非常好的方法。本文旨在为您提供一种将列表用作字典键的有效且相对安全的方法。
概念化这个混乱字典键必须具有可比性,以确保相等性,必须提供适当的哈希码,并且必须不可变。这些要求使使用列表作为字典键有点麻烦,因为列表通常不提供值语义——在这种情况下,是逐项比较和适当的哈希码。也许更糟的是,列表允许您随时修改它们。
总之,这里有两个主要问题,一个是逐项比较列表不是很有效,并且使用标准IList实现作为字典键从根本上是不安全的,因为可以随时对其进行修改。
我们可以通过要求使用IReadOnlyList来或多或少地解决后者,后者提供类似列表的访问,而不需要修改列表的方法。不过,当我们声明KeyList类时,我们将在其中添加一个Add()方法。这样做的原因是允许您首先填写列表。如果我们想更加安全,则可以取消该Add()方法,并强制您将这些项作为数组传递给KeyList的构造函数。未执行此操作的原因是为了提高性能。KeyList的主要目的是性能,将数据传递给构造函数将需要一个副本。副本不一定很慢,但我们不需要它——我们在这里没事,因为任何采用IReadOnlyList的操作都不会看到Add() 方法,这样,我们就避免了虚假的副本。
前者需要做更多的工作。我们必须在KeyList上实现值相等语义。但是,在这里,我们提出了一个重要的技巧:在将每个项目添加到列表时,我们都会重新计算哈希码,这样我们就不必在以后进行计算。然后,我们将该哈希码用作相等性检查的一部分,以在它们不相等时短路。接下来,让我们看一下该KeyList类的代码。
编码此混乱sealed class KeyList : IReadOnlyList, IEquatable
{
int _hashCode;
List _items;
public KeyList()
{
_items = new List();
_hashCode = 0;
}
public KeyList(int capacity)
{
_items = new List(capacity);
_hashCode = 0;
}
public T this[int index] => _items[index];
public int Count => _items.Count;
public IEnumerator GetEnumerator()
{
return _items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
public void Add(T item)
{
_items.Add(item);
if (null != item)
_hashCode ^= item.GetHashCode();
}
public override int GetHashCode()
{
return _hashCode;
}
public bool Equals(KeyList rhs)
{
if (ReferenceEquals(this, rhs))
return true;
if (ReferenceEquals(rhs, null))
return false;
if (rhs._hashCode != _hashCode)
return false;
var ic = _items.Count;
if (ic != rhs._items.Count)
return false;
for(var i = 0;i
关注
打赏
最近更新
- 深拷贝和浅拷贝的区别(重点)
- 【Vue】走进Vue框架世界
- 【云服务器】项目部署—搭建网站—vue电商后台管理系统
- 【React介绍】 一文带你深入React
- 【React】React组件实例的三大属性之state,props,refs(你学废了吗)
- 【脚手架VueCLI】从零开始,创建一个VUE项目
- 【React】深入理解React组件生命周期----图文详解(含代码)
- 【React】DOM的Diffing算法是什么?以及DOM中key的作用----经典面试题
- 【React】1_使用React脚手架创建项目步骤--------详解(含项目结构说明)
- 【React】2_如何使用react脚手架写一个简单的页面?


微信扫码登录