В чем разница между ref, out и in?
Только в различных условиях выполнения?
Т.е ref не обязан ничего присваивать и он изменяет основную переменную, переданную в метод в случае изменений.
out делает тоже самое, но обязывает что-то присвоить.
in разрешает только смотреть переменную.
В теории как своего рода модификаторы доступа можно представить?
Ответы (1 шт):
Все данные 3 ключевых слова передают ссылку (аналогично &T в C++).
Передавая ref в метод мы передаём ссылку на участок памяти со значением этой переменной, и изменяя это переменную меняется тот самый участок памяти. Мы можем изменять как бы оригинальную переменную, и даже присваивать ей новое значение
int someValue = 5;
add(ref someValue)
Console.WriteLine(someValue) // 6
void add(ref int i) => i++;
out и in это ограниченные версии ref
out позволяет получить ссылку, однако не позволяет читать из неё внешнее значение. Таким образом out гарантирует, вы что должны передать ref из которого 100% сотрутся любые данные. По этой же причине out обязывает тебя присвоить ей что то (даже если это null). Out используется например в tryGetValue который позволяет одновременно проверить, имеется ли свойство, и получить значение
bool tryGetValue(int id, out object? x){
if (data.Contains(id)) {
x = data.get(id);
return true;
}
// Главная цель затереть предыдущие данные из ref
// Поэтому мы можем присвоить переменной значение null
x = null;
return false;
}
in же в свою очередь предоставляет ref без возможности записи. Используется он очень редко, например у тебя имеется большая структура, или массив на стеке. Передавая его в метод он полностью копируется, чего мы можем избежать передавая только ССЫЛКУ на него. in гарантирует, что ссылка не будет изменена. Обычно она полезна при работе с динамическими библиотеками (т. к. обычно они возвращают указатели на структуры)
HugeData someData = new HugeData();
displayData(in someData); // someData не копируется
void displayData(in HugeData data) => ...
struct HugeData {
// Много данных
}
// btw структуры являются типами значений (как и int, short и т. п.)
// это значит что обычно они лежат на стеке
// и при передаче в виде аргумента копируются
// при этом изменяя их оригинал не меняется, как с объектами