我想最大程度地减少数学库中结构的复制,并阅读有关C#7.2 in
修饰符的信息,尤其是将其与 mutable 结构一起使用时的警告。
碰巧我有这个可变结构:
public struct Quaternion
{
public float W;
public float X;
public float Y;
public float Z;
}
到目前为止,该库具有类似这样的方法,其中的参数由ref
传递:
public static void Dot(ref Quaternion left,ref Quaternion right,out float result)
=> result = left.W * right.W + left.X * right.X + left.Y * right.Y + left.Z * right.Z;
从MSDN文档中,我了解到,如果将它们更改为in
参数,只要我仅是可变结构的 access字段,自编译器以来就不会发生防御性复制看到我没有修改可变结构:
public static void Dot(in Quaternion left,in Quaternion right,out float result)
=> result = left.W * right.W + left.X * right.X + left.Y * right.Y + left.Z * right.Z;
第一个问题:我对这种行为的理解正确吗?
第二个愚蠢的问题:如果在其中一种将结构作为in
参数接受的方法中,如果我调用另一个将其作为in
参数接受的方法,编译器是否会复制它? 示例:
public static void Lerp(in Quaternion start,in Quaternion end,float amount,out Quaternion result)
{
float inv = 1.0f - amount;
if (Dot(start,end) >= 0.0f) // will 2 copies be created here?
{
result.W = inv * start.W + amount * end.W;
result.X = inv * start.X + amount * end.X;
result.Y = inv * start.Y + amount * end.Y;
result.Z = inv * start.Z + amount * end.Z;
}
else
{
result.W = inv * start.W - amount * end.W;
result.X = inv * start.X - amount * end.X;
result.Y = inv * start.Y - amount * end.Y;
result.Z = inv * start.Z - amount * end.Z;
}
result.Normalize();
}
我很确定不应该 创建副本-那么我该如何阻止呼叫方的副本呢?但由于不确定,我最好先问清楚再制造一团糟。
附录
我想将ref
更改为in
的原因:
- (
static
)readonly
字段(例如特定的常数四元数)不能作为ref
自变量传递。 - 我无法在运算符参数上指定
ref
,但可以使用in
。 - 在呼叫站点上连续指定
ref
很丑。 - 我知道我必须在任何地方更改呼叫站点,但这没关系,因为该库只能在内部使用。