Whilst the other two answers are correct that in
parameters end up as ref
parameters in the resultant IL, care should be taken with the claim that this prevents the value being copied. This only holds true for readonly structs.
To demonstrate this, consider the following piece of code:
using System;
public struct S1
{
public int A;
public void ChangeA(int a) => A = a;
}
public static class Program
{
static void Main()
{
var s1 = new S1 { A = 1 };
S1Foo(in s1);
Console.WriteLine(s1.A);
}
private static void S1Foo(in S1 s) => s.ChangeA(2);
}
Since we are passing s1
by reference, one might reasonably assume that S1Foo
, in calling ChangeA
would then change the contents of s1
. This doesn't happen though. The reason being that the s1
value is copied and a copy is passed by reference, to prevent such modifications of structs via in
parameters.
If we decompile the resultant IL, you see that the code ends up as:
public static class Program
{
private static void Main()
{
S1 s = default(S1);
s.A = 1;
S1 s2 = s;
Program.S1Foo(ref s2);
Console.WriteLine(s2.A);
}
private static void S1Foo([IsReadOnly] [In] ref S1 s)
{
S1 s2 = s;
s2.ChangeA(2);
}
}
However, if we write similar code using a readonly struct
, then no copying occurs. I say similar as it isn't possible to write the same code as fields and property have to be readonly in a readonly struct (the clue is in the name):
using System;
public readonly struct S2
{
private readonly int _a;
public int A => _a;
public S2(int a) => _a = a;
public void ChangeA(int a) { }
}
public static class Program
{
static void Main()
{
var s2 = new S2(1);
S2Foo(in s2);
Console.WriteLine(s2.A);
}
private static void S2Foo(in S2 s) => s.ChangeA(2);
}
Then no copy occurs in the resultant IL.
So in summary:
in
is effectively a readonly ref
,
- The value (or reference) is passed by reference,
- The compiler prevents modifying fields and properties of that reference to help enforce its readonly-ness,
- To further enforce the readonly nature of the parameter, then non-readonly structs are copied before a reference to the copy is passed to the method. This doesn't occur for readonly structs.