如何高效检查C#中ReadOnlyMemory<char>是否存在于HashSet中?
高效检查ReadOnlyMemory在集合中的存在性
要在内存高效的前提下检查ReadOnlyMemory<char>是否存在于HashSet或其他集合中,核心问题是.NET默认对ReadOnlyMemory<char>的相等判断基于内存引用而非内容,所以必须通过自定义相等比较器实现内容匹配,但可以借助.NET内置扩展方法高效完成,完全避免字符串转换。
方案1:自定义IEqualityComparer<ReadOnlyMemory>
这是最直接的方案,利用MemoryExtensions提供的方法实现内容相等判断和哈希计算,无额外内存分配:
public class ReadOnlyMemoryCharEqualityComparer : IEqualityComparer<ReadOnlyMemory<char>> { public bool Equals(ReadOnlyMemory<char> x, ReadOnlyMemory<char> y) { // 直接比较Span内容,无内存分配 return x.Span.SequenceEqual(y.Span); } public int GetHashCode(ReadOnlyMemory<char> obj) { // 使用.NET内置的Span哈希算法,匹配字符串Ordinal比较逻辑 return obj.Span.GetHashCode(StringComparison.Ordinal); } }
使用方式:
// 初始化HashSet时传入自定义比较器 var memorySet = new HashSet<ReadOnlyMemory<char>>(new ReadOnlyMemoryCharEqualityComparer()); // 添加元素 memorySet.Add("example".AsMemory()); // 检查存在性 bool exists = memorySet.Contains("example".AsMemory());
方案2:使用FrozenSet提升查询性能
如果集合是只读的,推荐用System.Collections.Frozen命名空间下的FrozenSet——它会在构建时预计算哈希值,后续查询性能比普通HashSet更高,同样需要传入自定义比较器:
using System.Collections.Frozen; // 构建只读的FrozenSet var frozenMemorySet = new[] { "foo".AsMemory(), "bar".AsMemory() } .ToFrozenSet(new ReadOnlyMemoryCharEqualityComparer()); // 查询效率更优 bool exists = frozenMemorySet.Contains("foo".AsMemory());
注意事项
- 确保
ReadOnlyMemory<char>指向的内存在集合生命周期内始终有效,避免引用栈上临时内存或已释放的堆内存,否则会导致无效内存访问。 - 若需区分大小写或特定文化的比较,可修改
GetHashCode和Equals中的字符串比较规则(比如用StringComparison.OrdinalIgnoreCase)。
目前.NET原生没有无需自定义比较器的解决方案,因为ReadOnlyMemory<T>的默认相等逻辑基于内存地址而非内容。上述方案已是内存效率和性能最优的选择,完全避免了字符串转换带来的额外内存分配。
内容的提问来源于stack exchange,提问作者edwp
相关产品推荐
相关产品推荐

