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

如何在不将struct设为readonly的前提下,避免使用in参数的性能损耗?

这个问题问到点子上了——C# 7.2里的in参数和readonly struct确实是一对互补但有约束的特性,想要同时攥住「引用传递无拷贝」「编译时禁止参数重赋值」「能修改struct字段」这三个好处,咱们可以分两种场景来解决:

先理清核心矛盾

首先快速回顾下背景,帮你明确痛点:

  • in参数:按引用传递,编译时禁止给参数本身赋值(比如param = new Coord()),但对于可变struct,编译器会生成防御性拷贝——相当于你拿到的是拷贝后的实例,修改字段不会影响原对象,还平白多了拷贝开销。
  • readonly struct:完美解决防御性拷贝问题,但要求所有字段都是readonly,自动属性也得是只读的,直接封死了修改字段的可能。
解决方案1:用readonly struct配合引用类型字段实现“可变”

如果你的struct可以用引用类型来承载可变状态,那就能绕开readonly struct的字段只读限制。比如把可变的数值存在一个readonly的数组里(数组是引用类型,字段本身只是一个固定的引用,不会被修改):

public readonly struct MutableCoord {
    // 字段是readonly的,但数组内部元素可以修改
    private readonly int[] _coords;

    public int X {
        get => _coords[0];
        set => _coords[0] = value; // 修改数组元素,不改变字段本身的引用
    }
    public int Y {
        get => _coords[1];
        set => _coords[1] = value;
    }

    public MutableCoord(int x, int y) {
        _coords = new int[] { x, y };
    }
}

然后用in参数传递这个struct时:

public void UpdateCoords(in MutableCoord coord) {
    // 编译错误!in参数禁止重赋值,完美满足你的编译时检查需求
    // coord = new MutableCoord(0, 0);

    // 可以正常修改属性,且不会触发防御性拷贝(因为是readonly struct)
    coord.X += 10;
    coord.Y += 10;
}

这个方案完全命中你的所有需求:

  • 继承in参数的编译时检查:不能给参数重赋值
  • 无防御性拷贝:因为是readonly struct,编译器确认不会修改字段引用,直接按引用传递
  • 可以修改struct的状态:通过引用类型字段间接实现,效果和直接改字段一致
解决方案2:用ref参数+代码约定(或自定义分析器)

如果你不想引入引用类型的额外开销,想保持struct纯粹的“值类型”特性,那可以直接用ref参数——它本身就是按引用传递无拷贝,也能修改字段,但默认允许给参数重赋值。

想要实现编译时禁止重赋值的话,有两个办法:

  1. 团队内部约定:不在方法内给ref参数赋值
  2. 编写Roslyn分析器:自定义规则检查方法内是否对指定ref参数进行了赋值操作,触发编译警告/错误

示例代码:

public struct Coord {
    public int X, Y;
}

public void UpdateCoords(ref Coord coord) {
    // 如果有自定义分析器,这行会触发编译错误
    // coord = new Coord(0, 0);

    // 可以正常修改字段,全程无拷贝
    coord.X += 10;
    coord.Y += 10;
}

这个方案更直接,适合对性能极致追求的场景,缺点是需要额外的约定或工具来实现编译时检查。

总结

如果要严格满足所有需求且不依赖额外工具,优先选方案1;如果追求struct的纯粹值类型特性,方案2配合代码约定或分析器是更好的选择。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 06:59:40