Копирует ли передаваемая изменяемая структура в качестве параметра in через несколько методов? - PullRequest
2 голосов
/ 04 ноября 2019

Я хочу минимизировать копирование структур в математической библиотеке и прочитать о модификаторе C # 7.2 in, особенно о предупреждениях при использовании его с изменяемым структурами.

Это так происходитчто у меня есть эта изменчивая структура:

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 параметры, при условии, что я только получаю доступ к полям изменяемой структуры, защитная копия не произойдет, так как компилятор видит, что я не изменяю изменяемую структуру:

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 на сайте вызовов ужасно.
  • Я знаю, что мне нужно везде менять сайт вызовов, но это нормально, так какэта библиотека будет использоваться только для внутреннего использования.
...