MineR
MineR

Reputation: 2204

Is it necessary to use the "in" modifier with a readonly struct?

In C# 7.2, are readonly structs always passed to functions as if the "in" parameter is present? If not, in what case would it be useful to copy the memory given that it's readonly?

I have a readonly struct:

public readonly struct Vec2 
{
     public readonly double X;
     public readonly double Y;
}

So would there be a performance difference between these two methods when called billions of times:

public double Magnitude1(Vec2 v)
{
    return Math.Sqrt(v.X*v.X + v.Y*v.Y);
}
public double Magnitude2(in Vec2 v)
{
    return Math.Sqrt(v.X*v.X + v.Y*v.Y);
}

And if so, why doesn't the compiler recognize that Vec2 is a readonly struct and just pass it as if "in" were present? Is there an instance where you might want to pass a readonly struct without the "in" modifier?

Upvotes: 10

Views: 746

Answers (1)

Michael Liu
Michael Liu

Reputation: 55469

Are readonly structs always passed to functions as if the "in" parameter is present?

No. Without the in modifier, readonly structs are passed by value, not by reference.

If not, in what case would it be useful to copy the memory given that it's readonly?

It would be useful to copy the memory if you wanted to guarantee the memory didn't change. Keep in mind that a struct can be changed even if it's readonly. For example:

readonly struct S
{
    public readonly int I;

    public S(int i) { this.I = i; }
}

class Program
{
    static S s1 = new S(1);

    static void Main()
    {
        A(s1);
    }

    static void A(in S s2)
    {
        Console.Write(s2.I);
        s1 = new S(2); // This is legal even though S is readonly!
        Console.Write(s2.I);
    }
}

With the in modifier on parameter s2, the output is 12. Without the in modifier, the output is 11.

This difference in behavior means the compiler cannot transparently add in modifiers to readonly struct parameters. (Even if method A didn't modify s1, another thread could.)

So would there be a performance difference between these two methods when called billions of times?

There might be; measure it and see. I'd expect that the larger the struct, the slower it would be to pass by value.

And if so, why doesn't the compiler recognize that Vec2 is a readonly struct and just pass it as if "in" were present? Is there an instance where you might want to pass a readonly struct without the "in" modifier?

Maybe if the struct were very small (say, 8 bytes or less), passing by value (e.g., in a CPU register) could be cheaper than passing by reference (and then having to dereference the pointer).

Upvotes: 11

Related Questions