Для классов это буквально не имеет никакого значения;Вы всегда имеете дело со ссылкой и смещением от этой ссылки. Передача ссылки довольно дешево.
Когда она действительно начинает иметь значение с структурами . Обратите внимание, что это не влияет на вызов методов для типа - обычно это статический вызов на основе ref;но когда структура является параметром для метода, это имеет значение.
(edit: фактически, это также имеет значение при вызове методов для структур , если вы вызываетеих с помощью операции бокса, поскольку коробка также является копией; это отличная причина избегать коробочных вызовов!)
Отказ от ответственности: вы вероятно не должны регулярно использовать структуры.
Для структур значение занимает столько места везде, где оно используется в качестве значения , которое может быть в качестве поля, локальным в стеке, параметром дляметод и т. д. Это также означает, что копирование структуры (например, для передачи в качестве параметра) может быть дорогостоящим. Но если мы возьмем пример:
struct MyBigStruct {
// lots of fields here
}
void Foo() {
MyBigStruct x = ...
Bar(x);
}
void Bar(MyBigStruct s) {...}
, то в тот момент, когда мы вызываем Bar(x)
, мы копируем структуру в стеке. Точно так же всякий раз, когда локальный используется для хранения (при условии, что он не выкипает компилятором):
MyBigStruct x = ...
MyBigStruct asCopy = x;
Но! мы можем исправить это ... передав вместо этого reference . В текущих версиях C # это делается наиболее подходящим образом с использованием in
, ref readonly
и readonly struct
:
readonly struct MyBigStruct {
// lots of readonly fields here
}
void Foo() {
MyBigStruct x = ...
Bar(x); // note that "in" is implicit when needed, unlike "ref" or "out"
ref readonly MyBigStruct asRef = ref x;
}
void Bar(in MyBigStruct s) {...}
Теперь существует ноль фактических копий. Все здесь имеет дело со ссылками на оригинал x
. Тот факт, что это readonly
, означает, что среда выполнения знает, что она может доверять объявлению in
для параметра, не нуждаясь в защитной копии значения.
По иронии судьбы, возможно: добавление in
модификатор параметра может вводить копирование, если тип ввода - struct
, который не помечен readonly
, поскольку компилятор и среда выполнения должны гарантировать, что изменения, сделанные внутри Bar
, не будут видныдля звонящего. Эти изменения не должны быть очевидными - любой вызов метода (который включает средства получения свойств и некоторые операторы) может изменить значение, если тип является злым. В качестве злого примера:
struct Evil
{
private int _count;
public int Count => _count++;
}
Работа компилятора и среды выполнения состоит в том, чтобы работать предсказуемо , даже если вы злой, поэтому он добавляет защитную копию структуры. Тот же код с модификатором readonly
в структуре не скомпилирует .
Вы также можете сделать что-то похожее на in
с ref
, если тип isn 't readonly
, но тогда вам необходимо знать, что если Bar
изменяет значение (намеренно или как побочный эффект), эти изменения будут видны Foo
.