readonly struct实现的接口以in参数传递时能否避免值拷贝?
核心问题:in修饰接口参数时,传入readonly struct能否避免值拷贝?
结论:无法避免值拷贝,反而会触发装箱
当方法参数是接口类型(哪怕用in修饰),传入readonly struct实例时,必然会发生装箱操作——结构体的内容会被完整拷贝到托管堆的装箱对象中。此时in修饰符仅作用于装箱后的接口引用(避免引用本身的拷贝,但结构体的拷贝已经发生了),完全达不到你预期的“避免结构体拷贝”的性能优化效果。
原因分析
接口属于引用类型语义,值类型(包括readonly struct)要转换为接口类型,CLR必须执行装箱:将值类型实例的所有字段拷贝到堆上的一个新对象中,再把这个对象的引用作为接口参数传递。这个拷贝过程是无法通过in修饰符规避的。
而直接用in修饰具体readonly struct类型的参数(比如你的DoSomething(in SomeStruct someStruct)),则是值语义的传递:CLR直接传递结构体在栈上的内存地址,不会拷贝结构体内容,这才是真正实现无拷贝的场景。
替代方案:泛型约束+in修饰符
如果既要保留接口的抽象性,又要维持readonly struct的无拷贝优势,可以在.NET 7及以上版本使用泛型+结构体约束的方式:
public void DoSomethingElse<T>(in T instance) where T : struct, ISomeInterface
这种写法下,泛型参数T是具体的readonly struct类型,调用时不会触发装箱,in修饰符可以正常发挥作用,避免结构体拷贝。
内容的提问来源于stack exchange,提问作者Ginger and Lavender
相关产品推荐
相关产品推荐

