为多个参数创建唯一键(缓存键)

Creating a unique key (cache key) for multiple parameters

我有一个基于 3 个参数缓存数据的方法。例如:

  1. 状态
  2. 年龄
  3. 兄弟姐妹人数。

现在我的系统中有很多排列,它们保存在字典中:

Dictionary<string,MyObject> cache;

字典的键是三者的组合,用 string.format 完成(像这样):

public string CreateKey(eState state, int age, int numberOfSibilings)
{
    return string.format("{0}#{1}#{2}", state.ToString(), age.ToString(), numberOfSibilings.ToString());
}

eState 是一个 enum(int).

CreateKey 方法被调用了很多次并且是一个性能障碍,因为 string.format 不是特别快并且创建大量不可变字符串并不是最好的做法。

密钥可以包含用 * 替换的空条目。 CreateKey 方法在输入可空值时处理它们并检查它们是否具有值。

我相信有更好的方法来做到这一点。由于 eStateint,我考虑过使用数学公式以更快的方式创建密钥,但我想不出快速且独特的方法。

无论如何,我愿意接受您可以提供的任何解决方案,以尽可能快速和内存友好地创建唯一密钥。

当代码对性能至关重要时,

string.format 并不是那么好。它采用 Object 类型的参数,这意味着您需要将 int 和其他值类型装箱。

您可以创建一个自定义结构,用作字典的键。您需要在您的结构中实现 IEquatable<MyKey> 以便在调用 Equals 方法时不需要装箱。

public struct MyKey : IEquatable<MyKey>
{
    public readonly eState State;
    public readonly int Age;
    public readonly int NumberOfSibilings;

   ...Implement Equals method here
}

然后使用

Dictionary<MyKey ,MyObject> cache;
public MyKey CreateKey(eState state, int age, int numberOfSibilings)
{
    return new MyKey(state, age, numberOfSibilings);
}

这样您就不必在 CreateKey 方法中创建很多字符串。没有转换;您只需将它们存储为 int 并枚举本身。没有调用涉及拳击的 Enum.ToString(我猜)。使用我们的 MyKey 结构,没有任何装箱。这意味着更好的性能。

如果您正在寻找调试器友好的密钥(在评论中提到),您可以使用 DebuggerDisplay 属性。

[DebuggerDisplay("State= {State} Age= {Age}")]
public struct MyKey : IEquatable<MyKey>

您也可以使用元组作为密钥:

Dictionary<Tuple<eState, int, int>, MyObject> dict;

元组像这样计算相等性:

  • 它是一个 Tuple<T1, T2, T3> 对象
  • 它的三个组成部分与被比较的元组类型相同
  • 使用默认 Equals 方法,每个值都相等。

https://msdn.microsoft.com/en-us/library/dd387109(v=vs.110).aspx

优点是您不必创建新类型来保存密钥,它对元组中的任何类型都使用相等比较器,并且易于使用:

var myKey = new Tuple<eState, int, int>(eState.Whatever, 10, 15);
dict.Add(myKey, myObject)