Конструктор C #, параметр объекта передается по ссылке или значению - PullRequest
10 голосов
/ 06 января 2011

Если у вас есть класс и конструктор, который принимает объект в качестве входного параметра - этот объект передается по ссылке или по значению?

И верно ли предположить, что для методов класса входные параметры объекта по умолчанию передаются по значению, если не используется ключевое слово ref?

А как насчет ключевого слова out? Означает ли это, что оно передается по ссылке?

Ответы [ 7 ]

17 голосов
/ 06 января 2011

Если у вас есть класс и конструктор, который принимает объект в качестве входного параметра - этот объект передается по ссылке или по значению?

Все параметры передаются по значению в C #, если параметр не помечен out или ref.

Это огромный источник путаницы. Я изложу вещи немного более явно.

Все параметры имеют свои скопированные значения, если параметр не помечен out или ref. Для типов значений это означает, что создается копия передаваемого значения. Для ссылочных типов это означает, что копия ссылки сделана. Для этой последней точки значение ссылочного типа является ссылкой.

И верно ли предположить, что для методов класса входные параметры объекта по умолчанию передаются по значению, если не используется ключевое слово ref?

Опять же, все параметры передаются по значению в C #, если параметр не помечен out или ref. Для параметра, отмеченного ref, в метод передается ссылка на параметр, и теперь вы можете рассматривать этот параметр как псевдоним. Таким образом, когда вы говорите

void M(ref int m) { m = 10; }

int n = 123;
M(ref n);

вы можете думать о m в M как о псевдониме n. То есть m и n - это просто два разных имени для одного и того же места хранения.

Это очень отличается от

string s = "Hello, world!";
string t = s;

В этом случае s и t не являются одинаковыми для одного и того же места хранения. Это две разные переменные, которые ссылаются на один и тот же объект.

А как насчет ключевого слова `out? Означает ли это, что оно передается по ссылке?

Единственная разница между ref и out заключается в том, что ref требует инициализации переменной перед ее передачей.

13 голосов
/ 06 января 2011

ссылка на объект будет передана по значению.

.NET имеет ссылочные типы и типы значений - все классы являются ссылочными типами, а структуры - типами значений. Вы можете передать один по значению или по ссылке.

По умолчанию все передается по значению, с той разницей, что с типами ссылок передается ссылка .

Ключевые слова ref и out будут вызывать передачу параметров по ссылке - в случае типов значений это означает, что теперь вы можете вносить изменения, которые будут отражены в переданном объекте. С ссылочными типами это означает, что теперь вы можете изменить объект, на который ссылается ссылка.

3 голосов
/ 06 января 2011

object всегда передается по ссылке на фактический объект. Таким образом, для объекта не выполняется копирование (или «по значению»).

Так же, как отмечает Одед , ссылка на объект копируется.

1 голос
/ 21 мая 2011

@ Supercat: Это довольно интересно.Возможно, путаница заключается в понимании того, почему вы хотите передать ссылочный тип по ссылке!

Расширение аналогии только для типов ссылок (я думаю, что типы значений легче понять)

Можно записать один и тот же VIN (номер транспортного средства) на нескольких листах бумаги, отсюда и всепромахи на руке относятся к той же машине.Что если вы напишите «синей краской» на одном листе и «красной краской» на другой?это демонстрирует, что накладные могут содержать только VIN (адрес объекта), а вся другая информация хранится в самом автомобиле.

Если вы заинтересованы в покраске автомобиля в мастерской, вам не нужно отправлять квитанцию, вы можете просто сообщить им VIN ... это нужно только знать, передать значениевал.Вы по-прежнему держите квитанцию, и они не могут изменить то, что написано на вашей квитанции ... следовательно, это безопаснее.Поэтому они записывают VIN на своем собственном бланке - копию справки.

С другой стороны, вы можете попросить коллегу достать бланк для последней промытой машины с полки, перейти к привокзальной площадке и выбратьавтомобиль, который не является последним вымытым автомобилем и вернуть бланк с новым VIN помытого автомобиля, написанным на нем - реф.Используется фактическая квитанция, и вы сослались на адрес фактической квитанции (полки), чтобы он получил квитанцию ​​оттуда.Ему лучше не терять его и не намочить ... менее безопасно.

Во всей этой палаве никто не говорит о копировании, захвате или перемещении реальной машины, поскольку это НЕ относится к типам значений.

1 голос
/ 06 января 2011

Важная вещь, которую нужно понять с ссылочными типами, состоит в том, что почти все, что каждый делает с переменной ссылочного типа, неявно делается с вещью, на которую ссылается ссылка, а не с самой ссылкой.Я считаю полезным думать о ссылочных типах как об идентификаторах экземпляров.Чтобы использовать аналогию, представьте себе экземпляры как автомобили, а ссылочные типы - как листки бумаги с написанными на них идентификационными номерами автомобилей (VIN).Если я скопирую VIN на листок бумаги, передам его кому-нибудь в магазине и скажу «покрасьте этот синий», что я действительно имею в виду: «найдите автомобиль с этим VIN и покрасьте его в синий», а не «покрасьте этот слипбумаги голубой ".То, что я передаю человеку, это не машина, а просто VIN;однако я говорю ему, чтобы он покрасил в синий цвет, это машина, которая сидит в магазине, а не лист бумаги (или что-либо еще), который я ему на самом деле передаю.Такое использование будет передаваться по значению.

Предположим, однако, что я хотел, чтобы кто-то купил автомобиль и дал мне VIN.Я мог бы написать на листе бумаги нужную мне марку, модель, цвет и т. Д., А также вручить человеку листок бумаги, на котором можно написать VIN.В этом случае я хотел бы вернуть листок бумаги с новым VIN на нем.Такое использование будет передавать VIN по ссылке, так как человек будет писать VIN на листе бумаги, который я поставил, и вернуть его мне.

1 голос
/ 06 января 2011

Механизм передачи по умолчанию для параметров в .Net - по значению.Это верно как для ссылочных, так и для типов значений.В случае ссылки это фактическая ссылка, которая передается по значению, а не объекту.

Если используется ключевое слово ref или out, то значение действительно передается по ссылке (еще раз верно как для значения, так и для ссылочного типа).На уровне CLR фактически нет разницы между ref и out.Ключевое слово out является понятием C #, которое выражается маркировкой параметра ref (я полагаю, это сделано с помощью modopt)

0 голосов
/ 06 января 2011

Он передается по значению, если вы намеревались передать его по ссылке, вы бы использовали модификатор параметра ref. Хотя не уверен, разрешено ли это в конструкторах ...

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...