@ichernob

Что делает компилятор при передаче объекта по ссылке с явным преобразованием (ref(SomeClass)anotherSomeClass)?

Метод принимает аргументы, например, типа Animal, а передать туда нужно тип Dog, при этом, Dog является наследником Animal.
Компилятор ругается на строку
someMethod(ref (Animal)pet);
ошибкой "ref or out argument must be an assignable variable"
Гуглил ее, нашел только посты, в которых пытаются сделать примерно такое:
someMethod(ref new Dog());
В связи с чем возник вопрос. Разве компилятор создает новый объект при передаче аргументов по ссылке?
  • Вопрос задан
  • 369 просмотров
Решения вопроса 1
@raincons
В c# объекты всегда передаются по ссылке, но при передаче ref и out, грубо говоря, передается ссылка на ссылку. У ref параметра можно, а у out обязательно нужно вернуть новый объект.

Почему не разрешено приведение типов для ref и out:
class Animal...
class Dog : Animal...
class Cat : Animal...

void main()
{
  Dog dog = new Dog();
  someMethod(ref (Animal)dog);
  dog == ?
}

void someMethod(ref Animal pet)
{
  if (!(pet is Cat)) {
    pet.kill();
    pet = new Cat();
  }
}

какие должны быть значение и тип у переменной dog после вызова someMethod()?
Поэтому и ответ: при передаче ref и out параметра с приведением типа к базовому компилятор ничего не делает и выдает ошибку.
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 3
@dmitryKovalskiy
программист средней руки
Что вам мешает сделать приведение типа строкой выше и отправить новый параметр? Религиозные убеждения? Или премия за минимальное количество строк кода? Если вы передаете ссылочные типы в метод - то ref это просто огромный знак "Внимание, внутри могут изменить объект". C# всегда ссылочные типы передает по ссылке.

UPD : Читаем документацию :
Аргумент, который передается в параметр ref должен быть инициализирован перед передачей. В этом заключается отличие от параметров out, аргументы которых не требуют явной инициализации перед передачей.
Ответ написан
Немного от себя.
ref - передает не ссылку на ссылку или что либо еще.
ref - передает исходную ссылку (если ее занулить или изменить, то значение переменной передаваемой через ref тоже изменится).

(type A) type B - приведение типа (апкаст или даункаст) не создает новый объект, и даже не изменяет текущий, он просто интерпретирует объект одного типа как объект другого типа. (используется таблица методов)
Ответ написан
Комментировать
Nipheris
@Nipheris Куратор тега C#
> "ref or out argument must be an assignable variable"
вам же пишут - то, что вы передаете не является переменной (ну точнее, переменной, в которую можно что-то присвоить). Ссылка из переменной pet, скастованная к Animal - это уже "значение", а не "переменная". Вы можете запихнуть что-либо в pet, но не можете в (Animal)pet - т.к. это не переменная, а выражение, значение которого можно вычислить.
Как уже отметили выше, ref и out требуют передачи ПЕРЕМЕННОЙ в которую можно (и нужно в случае out) что-либо записать. И не имеет значения - ссылочный тип имеет переменная или тип-значение. Если вы передадите ref Dog, то в этот параметр можно будет записать ссылку на объект Dog, если передадите ref int - сюда можно будет записать int.
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы