Когда вы передаете [a readonly struct
] во входной параметр, компилятор видит, что он доступен только для чтения и не будет создавать защитную копию.
Я думаю, вы неправильно поняли.Компилятор создает защитную копию переменной только для чтения, которая содержит struct
(это может быть параметр in
, но также поле readonly
) при вызове метода для этого struct
.
Рассмотрим следующий код :
struct S
{
int x, y;
public void M() {}
}
class C
{
static void Foo()
{
S s = new S();
Bar(s);
}
static void Bar(in S s)
{
s.M();
}
}
Вы можете проверить сгенерированный IL для кода выше, чтобы увидеть, что на самом деле произойдет.
Для Foo
IL:
ldloca.s 0 // load address of the local s to the stack
initobj S // initialize struct S at the address on the stack
ldloca.s 0 // load address of the local s to the stack again
call void C::Bar(valuetype S&) // call Bar
ret // return
Обратите внимание, что копирование отсутствует: инициализируется локальный s
, а затем адрес этого локального объекта напрямую передается в Bar
.
IL для Bar
:
ldarg.0 // load argument s (which is an address) to the stack
ldobj S // copy the value from the address on the stack to the stack
stloc.0 // store the value from the stack to an unnamed local variable
ldloca.s 0 // load the address of the unnamed local variable to the stack
call instance void S::M() // call M
ret // return
Здесь инструкции ldobj
и stloc
создают защитную копию, чтобы убедиться, что если M
мутирует struct
, s
не будет видоизменяться (поскольку он доступен только для чтения).
Если вы измените код так, чтобы S
a readonly struct
, то IL для Foo
останетсято же самое, но для Bar
оно изменяется на:
ldarg.0 // load argument s (which is an address) to the stack
call instance void S::M() // call M
ret // return
Обратите внимание, что здесь больше нет копирования.
Это защитаскопируйте эту отметку struct
как readonly
.Но если вы не будете вызывать какие-либо методы экземпляра в структуре, защитных копий не будет.
Также обратите внимание, что язык диктует, что при выполнении кода он должен вести себя , как если бы защитная копия была там.Если JIT может выяснить, что копия на самом деле не нужна, разрешается избегать ее.