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

C#12中ref struct主构造函数ref-like类型参数实例成员使用报错CS9110原因?

关于C#12主构造函数在ref struct中访问ref-like参数的CS9110错误解析

问题场景

升级代码至C#12并尝试在合适场景使用主构造函数时,遇到以下问题:在一个接收ReadOnlySpan<char>(属于ref-like类型)作为构造参数的ref struct中,在实例方法MoveNext里直接访问主构造参数value时,触发CS9110错误:Cannot use primary constructor parameter that has ref-like type inside an instance member。

代码示例:

/// <summary>An utility like String.Split, but for Spans. This should avoid allocations.</summary>
internal ref struct CharSpanSplitter(ReadOnlySpan<char> value, char separator)
{
    // Uncomment to make the error go away
    //private ReadOnlySpan<char> value = value;

    public ReadOnlySpan<char> Current { get; private set; }

    public bool MoveNext()
    {
        // CS9110: Cannot use primary constructor parameter that has ref-like type inside an instance member.
        if (value == ReadOnlySpan<char>.Empty)
        {
            return false;
        }

        // CS9110: Cannot use primary constructor parameter that has ref-like type inside an instance member.
        var index = value.IndexOf(separator);
        if (index == -1)
        {
            // CS9110: Cannot use primary constructor parameter that has ref-like type inside an instance member.
            Current = value;
            
            // CS9110: Cannot use primary constructor parameter that has ref-like type inside an instance member.
            value = ReadOnlySpan<char>.Empty;
            return true;
        }

        // CS9110: Cannot use primary constructor parameter that has ref-like type inside an instance member.
        Current = value[..index];


        // CS9110: Cannot use primary constructor parameter that has ref-like type inside an instance member.
        value = value[(index + 1)..];
        return true;
    }
}

问题解答

1. 为何直接访问主构造参数不被允许?

主构造参数的默认作用域仅局限于构造函数执行阶段,本质上属于构造函数的局部变量。而ReadOnlySpan<char>这类ref-like类型的核心约束是:不能存在超出其声明生命周期的引用,否则会引发悬垂引用导致内存安全问题。

如果允许在实例方法中访问主构造的ref-like参数,编译器无法保证该参数的生命周期在实例方法调用时仍然有效——构造函数执行完成后,主构造参数的生命周期理论上已经结束,实例方法调用时再访问它,可能会引用到已经失效的内存区域。因此C#编译器通过CS9110错误禁止这种操作,从语法层面规避潜在的内存风险。

2. 赋值给私有字段后错误消失的原因?

当将主构造的ref-like参数赋值给ref struct的私有字段时,该字段的生命周期与ref struct实例本身绑定。由于ref struct是栈分配的类型,编译器可以完整跟踪实例的生命周期,确保实例方法执行时,字段中的ref-like类型引用始终处于有效状态,不会出现悬垂引用的问题。因此编译器允许这种访问方式,错误自然消失。


内容的提问来源于stack exchange,提问作者Steven Liekens

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.04 23:07:43