如何在C#中实现可返回ref的TryGetValue方法?
实现返回ref struct的TryGetValue替代方案
针对你需要实现类似Dictionary.TryGetValue但返回指向struct的ref的需求,以下是几种适配旧版C#环境的更优实现方式:
方案1:优化基础返回ref+out bool的调用体验
针对你提出的替代方案1,通过调整调用写法可避免作用域污染问题,同时保持实现简洁:
实现代码
private static readonly TValue s_dummy = default; // 复用dummy实例,避免重复分配 public ref TValue TryGetValue(TKey key, out bool found) { if (/* 查找逻辑:键存在 */) { found = true; return ref _internalStorage[key]; // 返回指向目标struct的ref } found = false; return ref s_dummy; // 返回dummy的ref,避免返回空ref }
调用方式
bool found; ref var targetVal = ref myDict.TryGetValue("key", out found); if (found) { doSomething(ref targetVal); }
这种写法将ref赋值与存在性判断分离,既符合旧版C#语法,也避免了作用域污染,同时dummy实例复用无额外性能开销。
方案2:给OptionalRef添加TryGetRef方法,贴近原生调用体验
基于你定义的OptionalRef<T>,新增TryGetRef方法,让调用逻辑和Dictionary.TryGetValue完全对齐:
扩展OptionalRef
public readonly ref struct OptionalRef<T> { // 原有的字段和构造函数保持不变... [MethodImpl(MethodImplOptions.AggressiveInlining)] public bool TryGetRef(out ref T value) { if (HasValue) { value = ref Value; return true; } // 旧版C#无Unsafe.NullRef时,返回dummy的ref value = ref s_dummy; return false; } // 若项目允许使用Unsafe,可替换为: // value = ref Unsafe.NullRef<T>(); }
调用方式
if (myDict.TryGetValue("key").TryGetRef(out ref var myVal)) { doSomething(ref myVal); }
这种写法完全复刻了原生TryGetValue的调用体验,同时保留返回ref的核心需求,无需升级C#版本。
方案3:Unsafe指针实现(需开启unsafe模式)
如果项目允许使用unsafe代码,可直接实现你最初设想的TValue**逻辑:
实现代码
unsafe public bool TryGetValue(TKey key, TValue** value) { if (/* 查找逻辑:键存在 */) { *value = &_internalStorage[key]; // 直接返回struct的指针 return true; } *value = null; return false; }
调用方式
unsafe { TValue* valPtr; if (myDict.TryGetValue("key", &valPtr) && valPtr != null) { ref var myVal = ref *valPtr; doSomething(ref myVal); } }
这种方式最贴近底层逻辑,但需要开启unsafe编译选项,适合对性能要求极高且允许unsafe的场景。
内容的提问来源于stack exchange,提问作者ph3rin
相关产品推荐
相关产品推荐

