Могу ли я рассматривать ссылочный тип как тип значения здесь, или мне нужно клонировать?

#c# #asp.net-core-3.1 #value-type #reference-type

#c# #asp.net-core-3.1 #тип значения #ссылочный тип

Вопрос:

Рассмотрим следующий метод:

 public (MySpecialType one, MySpecialType two) ReturnTwoSeparateObjects()
{
   MySpecialType before = new MySpecialType();
   MySpecialType after = before;
   after.MyProperty = "A value";
   return (before, after); // These will be the same object, pointless returning twice
}
  

Это вернет тот же объект, поскольку назначение after — это просто та же ссылка на память, выделенную для before . Я понимаю это, но я хочу вернуть представление объекта до и после изменения свойства.

Я знаю, что, вероятно, я могу глубоко клонировать before , используя сериализацию или что-то в этом роде, но это кажется довольно сложным подходом (я могу ошибаться в этом, это предположение). Предполагая, что я хотел избежать глубокого клонирования, есть ли какой-то способ рассматривать before его как тип значения здесь?

Ответ №1:

Ну, вам не нужно использовать сериализацию, но вам нужно создавать отдельные объекты. То, насколько глубоко вам нужно клонировать, будет зависеть от типа — например, вам не нужно клонировать какие-либо неизменяемые типы. (Чем больше неизменности вы можете ввести в свой код, тем проще это становится.)

Нет понятия «рассматривать ссылочный тип как тип значения», но даже если бы оно было, оно все равно естественным образом выполняло бы неглубокий клон, так что вам было бы не намного лучше.

Комментарии:

1. Спасибо, Джон. Это побудило углубиться в различные типы клонирования, и поскольку эти члены являются неизменяемыми, я думаю, что один из подходов, на который вы могли бы ссылаться, — это memberwise clone, я думаю, это делает то, что мне нужно. Еще раз спасибо

Ответ №2:

С появлением C # 9 у вас есть возможность определить MySpecialType as record вместо class , и сделать это:

 public (MySpecialType one, MySpecialType two) ReturnTwoSeparateObjects()
{
    var before = new MySpecialType();
    var after = before with { MyProperty = "A value" };
    return (before, after);
}
  

Метод вернет две разные ссылки, представляющие разные версии одного и того же объекта.

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