С# передать значение/ref?
Общий вопрос, но я мог бы использовать "английское" объяснение.
Ist это похоже на Java, где
Cat myCat
На самом деле это указатель на Cat?
Должен ли я создавать конструкторы копирования в С#?
Я понимаю, что мы проходим по значению, но теперь мой вопрос заключается в том, что мы передаем значение указателя или полную копию объекта?
если его последняя, разве это слишком дорогостоящая производительность/память? Это когда вам нужно использовать ключевое слово ref?
Ответы
Ответ 1
Как ответил @rstevens, если это класс, myCat является ссылкой. Но если вы передаете myCat вызову метода, то сама ссылка передается по значению - т.е. сам параметр будет ссылаться на тот же объект, но это совершенно новая ссылка, поэтому, если вы присваиваете ему значение null или создаете новый объект, старая ссылка myCat по-прежнему будет указывать на исходный объект.
SomeMethod(myCat);
void SomeMethod(Cat cat)
{
cat.Miau(); //will make the original myCat object to miau
cat = null; //only cat is set to null, myCat still points to the original object
}
У Джона Скита есть хорошая статья об этом.
Ответ 2
Помните, что указатель не совсем такой же, как ссылка, но вы можете просто подумать об этом так, как хотите.
Клянусь, я видел еще один вопрос о том, что это не 10 минут назад, но я не могу найти ссылку сейчас. В другом вопросе, который я видел, они говорили о передаче аргументов по соотношению vs по значению, и это сводилось к следующему:
По умолчанию в .Net вы не передаете объекты по ссылке. Вы передаете ссылки на объекты по значению.
Разница тонкая, но важная, особенно если вы, например, хотите назначить свой переданный объект в методе.
Ответ 3
Если вы делят Cat как
class Cat {...}
то это.
Если вы разделили Cat как
struct Cat {...}
то ваша переменная "есть" сама структура.
Это различие между ссылочными типами и типами значений в .Net.
Ответ 4
Да, это о указателях, но на самом деле... Дело в том, что это изначально связано с тем, что речь не идет о защите вашей переменной от изменений в методе. Если вы измените объект внутри метода, эти изменения будут видны внешним методам независимо от того, передано ли оно в "ref" или нет.
Разница (как я понимаю) заключается в том, будет ли переменная, которую вы отправляете, обновить ссылку, если вы измените объект, который ссылается на переменную. Так что данный метод
public void DoSomething(ref CoolShades glasses)
{
glasses.Vendor = "Ray Ban";
glasses = new CoolShades();
}
переменная, которую вы передали в качестве параметра, теперь содержит ссылку на новый CoolShades, а не на какой-либо объект, на который он ссылался ранее. Исходное свойство объекта Vendor объекта параметра будет изменено на "Ray Ban" независимо от того, прошел ли вы параметр ref или нет.