电话
400 9058 355
能,ref readonly参数可避免struct拷贝,但仅限传入可寻址左值且方法内不修改时;传右值会编译报错,in参数语义等价但更简洁安全。
能,但仅

ref readonly 允许你以只读引用方式传递 struct,彻底跳过值类型的默认按值复制行为——前提是调用方传入的是可寻址的左值(比如局部变量、数组元素、字段),而非临时对象(如字面量或 new 表达式结果)。
常见误区:以为加了 ref readonly 就“一定不拷贝”。其实如果传入的是不可寻址的右值(例如 SomeMethod(ref readonly new BigStruct())),编译器会报错 CS8337: Cannot use a result of 'new BigStruct()' as a ref or out value because it is not a variable,根本过不了编译。
当你需要高性能访问大型 struct(比如含多个 double 字段的几何类型、固定大小缓冲区等),又**明确禁止方法内部修改其状态**时,ref readonly 是唯一兼顾安全与零拷贝的选择。
ref 虽然也避免拷贝,但开放了写权限,容易破坏封装或引发意外副作用;而 readonly 修饰后,编译器会在方法体内对所有成员访问做只读检查:
param.x = 1; → 编译错误)readonly 成员方法(哪怕该方法逻辑上不修改状态)readonly 方法、访问属性(只要 getter 是 readonly)示例:
struct Matrix4x4
{
public double M11, M12, M13, M14;
// ... 16个double,约128字节
public readonly double Determinant => /* 计算逻辑 */;
}
void ProcessMatrix(ref readonly Matrix4x4 m)
{
Console.WriteLine(m.Determinant); // ✅ OK
// m.M11 = 0; // ❌ 编译错误
// m.ToString(); // ❌ 若ToString()不是readonly方法
}
它对调用端有严格要求,稍不注意就触发编译错误或隐式拷贝:
ProcessMatrix(ref readonly GetMatrix()) ❌)async 方法参数(因为 await 可能导致栈帧移动,引用失效)out 或 ref 参数重载的区分依据(void M(ref T) 和 void M(ref readonly T) 不能共存)string),ref readonly 只保证 struct 本身地址不变、字段不可改,但不阻止通过引用字段间接修改堆对象性能提示:对于小于 16 字节的小 struct(如 Point, Guid),按值传递反而可能更快——CPU 寄存器能直接承载,避免取地址和解引用开销。
C# 7.2 同时引入了 in 参数关键字,语义上等价于 ref readonly,但更简洁且意图更明确:
void M(in Matrix4x4 m) 等价于 void M(ref readonly Matrix4x4 m)
in 更推荐用于只读输入场景,编译器对其做了额外优化(如允许传入只读临时变量,某些情况下放宽右值限制)Span 配合 MemoryMarshal.AsBytes 更底层可控,但需 unsafe 或 System.Runtime.CompilerServices.Unsafe
真正复杂的地方在于:是否值得为避免一次拷贝,增加调用约束、破坏 API 易用性?尤其当 struct 生命周期短、调用频次低时,in 带来的收益可能被可维护性成本抵消。实际压测比理论推导更可靠。
邮箱:8955556@qq.com
Q Q:8955556
本文详解如何将Go官方present工具(用于生成HTML5...
PySNMP在不同版本中对SNMP错误状态(errorSta...
time.Sleep仅阻塞当前goroutine,其他gor...
PHPfopen()创建含特殊符号的文件名失败主因是操作系统...
WooCommerce中通过代码为分组产品动态聚合子商品的属...
io.ReadFull返回io.ErrUnexpectedE...
本文详解Yii2中控制器向视图传递ActiveRecord数...
本文详解为何通过wp_set_object_terms()为...
Pytest中使用@mock.patch类装饰器会导致补丁泄...
带缓冲的channel是并发安全的FIFO队列;make(c...