C# 通过多个方法将可变结构作为in参数传递是否会复制它?
我想尽量减少对数学库中结构的复制,并阅读修饰符中的C#7.2C# 通过多个方法将可变结构作为in参数传递是否会复制它?,c#,struct,c#-7.2,in-parameters,C#,Struct,C# 7.2,In Parameters,我想尽量减少对数学库中结构的复制,并阅读修饰符中的C#7.2,特别是在与可变结构一起使用时的警告 碰巧我有一个可变结构: 公共结构四元数 { 公共浮动W; 公共浮动X; 公众浮躁; 公共浮动Z; } 到目前为止,库中有这样的方法,其中参数通过ref传递: 公共静态空点(左参考四元数,右参考四元数,外浮点结果) =>result=left.W*right.W+left.X*right.X+left.Y*right.Y+left.Z*right.Z; 从MSDN文档中,我了解到,如果我在参数中将
,特别是在与可变结构一起使用时的警告
碰巧我有一个可变结构:
公共结构四元数
{
公共浮动W;
公共浮动X;
公众浮躁;
公共浮动Z;
}
到目前为止,库中有这样的方法,其中参数通过ref
传递:
公共静态空点(左参考四元数,右参考四元数,外浮点结果)
=>result=left.W*right.W+left.X*right.X+left.Y*right.Y+left.Z*right.Z;
从MSDN文档中,我了解到,如果我在
参数中将这些更改为,只要我只访问可变结构的字段,就不会发生防御复制,因为编译器看到我没有修改可变结构:
公共静态空点(左四元数、右四元数、外浮点结果)
=>result=left.W*right.W+left.X*right.X+left.Y*right.Y+left.Z*right.Z;
第一个问题:我对这种行为的理解正确吗
第二个愚蠢的问题:如果在其中一个方法中接受结构作为in
参数,那么如果我调用另一个方法将其作为in
参数接受,编译器会复制它吗?举个例子:
公共静态无效Lerp(在四元数开始时,在四元数结束时,浮动量,
输出四元数结果)
{
浮动库存=1.0f-金额;
如果(点(开始,结束)>=0.0f)//这里会创建两个副本吗?
{
结果W=存货*开始W+金额*结束W;
结果.X=inv*start.X+金额*end.X;
结果Y=存货*开始Y+金额*结束Y;
结果.Z=存货*开始.Z+金额*结束.Z;
}
其他的
{
result.W=inv*start.W-金额*end.W;
结果.X=inv*start.X-金额*end.X;
结果Y=存货*开始Y-金额*结束Y;
结果.Z=inv*start.Z-金额*end.Z;
}
result.Normalize();
}
我很确定它不应该创建拷贝——否则我怎么阻止来自呼叫端的拷贝呢?但我不确定,在制造混乱之前,我最好先问一下
附录
我想将ref
更改为中的原因:
- (
static
)readonly
字段(例如特定的常量四元数)不能作为ref
参数传递
- 我不能在操作符参数上指定
ref
,但我可以在
中使用
在呼叫站点上不断指定ref
,这很难看
我知道我必须在任何地方更改呼叫站点,但这没关系,因为这个库只在内部使用
在一般情况下,
中的可能会导致多个副本,因为运行时需要强制执行调用方法之类的操作不会产生任何副作用。如果类型标记为readonly struct
,则它信任不会更改类型的方法,但是:您的场景是非只读
值类型。在您的情况下,您没有调用方法-只访问字段;所以不太清楚的是,为什么一开始就使用可变结构?我见过的所有关于结构的最佳实践建议都在谈论如何使它们不可变……您关心的是性能还是语义?@ZoharPeled我过去使用的C#3D数学库通常不使用不可变结构,这也可能是因为它们在C#中不存在。实际上我在一个矩阵类型上试过这个。仍然有太多的代码只想更改矩阵的一个字段,所以我保留了可变字段。虽然它可能只适用于四元数,但出于问题的考虑,假设我必须根据用户期望使用可变的四元数。@500 InternalServerError性能在这里更为重要。如果不能保证不复制它们,我可能只能接受ref
。我在这里看到了一个使用新特性的机会,它的语义不那么冗长,而且显然没有性能成本,因为我只访问字段。