В c # массивы или списки передаются по умолчанию по ссылке?

86

А они? Или для ускорения моей программы я должен передать их по ссылке?

Хорхе Бранко
источник
35
Чтобы ускорить вашу программу, вы должны (1) установить значимые цели, (2) проверить, достигли ли вы своих целей, (3) если нет, использовать инструмент профилирования, чтобы найти самое медленное, и (4 ) оптимизировать самое медленное.
Эрик Липперт
1
См. Также stackoverflow.com/q/4311226/344822
prabhakaran 04
3
@EricLippert Ваш комментарий отвечает на реальный вопрос ОП намного лучше, чем любой из опубликованных ответов. Все были настолько сбиты с толку техническими деталями, как «передать ссылку по значению», что полностью упустили из виду реальный вопрос об оптимизации производительности. К сожалению, ОП сообщил о своих потребностях довольно плохо, а другие ответы, по крайней мере, помогут толпе Google.
Дэн Бечард,
«другие ответы, по крайней мере, помогут толпе Google» - они будут! :)
miki

Ответы:

210

Ссылка передается по значению .

Массивы в .NET - это объекты в куче, поэтому у вас есть ссылка. Эта ссылка передается по значению, что означает, что изменения содержимого массива будут видны вызывающей стороне, но переназначение массива не будет:

void Foo(int[] data) {
    data[0] = 1; // caller sees this
}
void Bar(int[] data) {
    data = new int[20]; // but not this
}

Если вы добавите refмодификатор, ссылка будет передана по ссылке - и вызывающий увидит любое изменение выше.

Марк Гравелл
источник
28
Ответ правильный, но я ненавижу людей, которые заявляют, что «ссылка передается по значению». Это сбивает с толку вопрос. Да, ссылки (адреса памяти) передаются по значению, но вопрос не в этом.
WernerVA
9
@WernerVA Мне интересно, как, по-вашему, вы бы выразили это по-другому, что остается правильным и недвусмысленным
Марк Грейвелл
2
Я бы не стал выражать это иначе, просто, возможно, немного подробнее.
WernerVA
Это не отвечает на вопрос о скорости. Вероятно, для вас очевидно, что оптимизация эталонной копии будет совершенно незначительной по сравнению с сотнями других, гораздо более дорогостоящих операций, которые происходят, но OP действительно спросил об этом.
Дэн Бечард,
7
@Dan, часть скорости по своей сути связана с тем, что «если массив передается по значению - то есть копия содержимого массива - это означает выделение и копию всей памяти». Поскольку это ссылка , которая передается, не вопрос производительности в ответ - эта часть вопроса оказывается спорным и ответил автоматически. За исключением того, что теперь на него также дан явный ответ в комментариях ...
Марк Грейвелл
10

Они передаются по значению (как и все параметры, которые не являются ни ref, ни out), но значение является ссылкой на объект, поэтому они фактически передаются по ссылке.

плинтус
источник
0

Да, в C # они по умолчанию передаются по ссылке. Все объекты в C #, кроме типов значений. Чтобы быть немного более точным, они передаются «по ссылке по значению»; то есть значение переменной, которое вы видите в своих методах, является ссылкой на исходный переданный объект. Это небольшой смысловой момент, но иногда он может быть важным.

Поль Сонье
источник
9
Ссылка передается по значению; что сильно отличается от «они передаются по ссылке».
Марк Гравелл
1
Это полная противоположность истине. Цитата из этого сообщения Джона Скита : «По умолчанию все параметры в C # передаются по значению. Параметры передаются только по ссылке, если вы явно включаете модификатор out или ref. Однако вы должны знать, что когда тип параметра является ссылочным типом, вы передаете ссылку, а не реальный объект ". По значению передается только ссылка (адрес памяти).
alexlomba87 04