如何在Lambda表达式内部修改ref引用变量?
问题描述
我希望在Lambda表达式内部为ref引用变量赋值,以下是简化后的最小可复现示例(MRE):
public class Foo { public int Value { get; private set; } public Foo(int value) => this.Value = value; } public class Test { Foo F1 = new Foo(1); Foo F2 = new Foo(2); // 库方法,无法修改 void LoadAsync(int value, Action<Foo> onSuccess) { // 这会在后续帧异步执行 Foo f = new Foo(value); onSuccess(f); } // 我的方法,可以修改参数和实现,但不能改返回类型 void LoadAndAssignAsync(int value, ref Foo fooToAssign) { LoadAsync(value, loadedFoo => fooToAssign = loadedFoo); // 此处不被允许 // 因为加载是异步的,我不能在这里赋值`fooToAssign`, // 必须在Lambda内部完成赋值 } void Start() { LoadAndAssignAsync(11, ref F1); // 希望保留这种简洁的调用方式 LoadAndAssignAsync(24, ref F2); // 我想要一种简洁的写法: // 加载完成后,把结果赋值给我指定的变量(字段) } }
Lambda无法捕获ref参数,当前写法不被允许。我希望找到简洁的替代方案,尽量保留ref F1这类简洁的调用方式,而非改用传递Lambda的繁琐写法。
注:此处的“异步”指Unity的协程机制,具体对应Addressables的AsyncOperationHandle操作。
解决方案
方案1:用包装类持有引用
创建简单的包装类来持有目标变量的引用,间接在Lambda中完成赋值,完全保留原有调用方式:
public class RefWrapper<T> { public T Value { get; set; } public RefWrapper(ref T value) => Value = value; } // 修改你的方法实现 void LoadAndAssignAsync(int value, ref Foo fooToAssign) { var wrapper = new RefWrapper<Foo>(ref fooToAssign); LoadAsync(value, loadedFoo => wrapper.Value = loadedFoo); }
方案2:重载方法封装赋值逻辑
通过重载方法把ref参数转换为赋值委托,调用端写法不变,内部适配异步方法要求:
// 对外暴露的ref参数重载,保持调用简洁 void LoadAndAssignAsync(int value, ref Foo fooToAssign) { LoadAndAssignAsync(value, f => fooToAssign = f); } // 内部实际调用的方法,接收赋值委托 void LoadAndAssignAsync(int value, Action<Foo> assignAction) { LoadAsync(value, assignAction); }
方案3:针对Unity场景的弱引用方案
如果是Unity类字段的场景,可以用弱引用避免额外类开销,注意仅适合字段(局部变量可能因生命周期回收失效):
void LoadAndAssignAsync(int value, ref Foo fooToAssign) { var weakRef = new WeakReference<Foo>(fooToAssign); LoadAsync(value, loadedFoo => { if (weakRef.TryGetTarget(out _)) { fooToAssign = loadedFoo; } }); }
内容的提问来源于stack exchange,提问作者bolov
相关产品推荐
相关产品推荐

