MemoryCache 在内部使用ConcurrentDictionary<object, CacheEntry>,而后者又使用object 类型的默认比较器,它根据Object.Equals 和Object.GetHashCode 的实际类型覆盖执行相等比较。在您的情况下,您的密钥是 ValueTuple<string, Query>,无论您的 Query 类是什么。 ValueTuple<T1,T2>.Equals 如果比较实例的组件与当前实例的组件类型相同,并且组件与当前实例的组件相同,则计算结果为 true,每个组件的相等性由默认相等比较器确定.
因此,如何执行相等比较取决于您的 Query 类型的实现。如果此类型没有覆盖Equals 和GetHashCode,也没有实现IEquatable<T>,则执行引用相等,这意味着您只有在传入同一个查询实例时才会得到相等。如果你想改变这种行为,你应该扩展你的Query类来实现IEquatable<Query>。
我还发现CreateEntry 不会立即将新条目添加到缓存中。 .NET Core 文档稀少得令人失望,所以我没有找到预期的行为;但是,您可以通过调用 Set 来确保添加条目。
例子:
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.Extensions.Caching.Memory;
class Program
{
static void Main(string[] args)
{
var query1 = new Query { Parts = { new List<string> { "abc", "def", "ghi" } } };
var query2 = new Query { Parts = { new List<string> { "abc", "def", "ghi" } } };
var memoryCache = new MemoryCache(new MemoryCacheOptions());
memoryCache.Set(("typeOfCache", query1), new object());
var found = memoryCache.TryGetValue(("typeOfCache", query2), out var something);
Console.WriteLine(found);
}
public class Query : IEquatable<Query>
{
public List<List<string>> Parts { get; } = new List<List<string>>();
public bool Equals(Query other)
{
if (ReferenceEquals(this, other)) return true;
if (ReferenceEquals(other, null)) return false;
return this.Parts.Length == other.Parts.Length
&& this.Parts.Zip(other.Parts, (x, y) => x.SequenceEqual(y)).All(b => b);
}
public override bool Equals(object obj)
{
return Equals(obj as Query);
}
public override int GetHashCode()
{
return this.Parts.SelectMany(p => p).Take(10).Aggregate(17, (acc, p) => acc * 23 + p?.GetHashCode() ?? 0);
}
}
}