You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何传递ref struct给方法实际是传副本?如何实现按引用传递?

问题描述

定义了如下ref struct:

public ref struct BufferWriter
{
    readonly Buffer* _pb;
    public int WrittenBytes;
    //...
    public bool Append(ReadOnlySpan<byte> buffer)
    {
        //...
        WrittenBytes += buffer.Length;
        //...
    }
    
}

将其传递给抽象方法Write100U8Chars(BufferWriter, Object)时,发现是按值传递而非引用传递:

protected override bool Serialize(object obj)
{
    //...
    fixed (Buffer* pb = &doc_body)
    {
        using (BufferWriter writer = new BufferWriter(pb))
        {
            writer.Append("UTF8 str"U8);
            // pb->Bytes 现在为8
            // writer.WrittenBytes 现在也为8
            Write100U8Chars(writer, obj);
            // pb->Bytes 现在为108
            // 但 writer.WrittenBytes 仍为8!
        }
    }
    //...
}

// 该方法始终调用BufferWriter.Append传入100个UTF-8字符(即字节) 
protected abstract bool Write100U8Chars(BufferWriter writer, object obj);

尝试移除using块、改为ref readonly struct、使用in参数传递均无效,writer.WrittenBytes始终未被方法内的修改同步回来。

请问如何让ref struct像普通非ref struct那样按引用传递给抽象方法?

解决方案
  • 给方法参数添加ref修饰符:这是实现引用传递的直接方式。修改抽象方法的参数定义,调用时也必须带上ref关键字,这样方法内对BufferWriter实例的修改会直接同步到外部。
    修改后的抽象方法:
    protected abstract bool Write100U8Chars(ref BufferWriter writer, object obj);
    
    调用代码:
    Write100U8Chars(ref writer, obj);
    
  • 澄清几个误区:
    • 不管是普通struct还是ref struct,默认都是值传递,必须显式用ref才能实现引用传递,和struct是否带ref修饰无关。
    • in参数是只读引用,只能读取实例成员,无法修改可变字段(比如WrittenBytes),所以用in无法同步修改结果。
    • ref readonly struct是只读的ref struct,本身限制了对可变成员的修改,自然也解决不了问题。
    • using块的作用是管理对象生命周期(调用Dispose),和参数传递的方式完全无关,移除它不会改变值传递的本质。

内容的提问来源于stack exchange,提问作者D-Kay

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.28 16:38:40