2013-03-05 2 views
-2

Мой вопрос касается использования объектов в C#. Кажется, я понимаю, что происходит, но я хочу понять, почему. По причинам, в которые я не буду входить, я хочу создать временную копию объекта с его текущими данными (текущее состояние). Поэтому я подумал, что могу создать новый объект, назначить ему оригинальный объект, а затем изменить исходный объект. В этот момент у меня было бы два объекта в разных состояниях. Но происходит то, что скопированный объект выглядит точно так же, как первый. Вот код для иллюстрации:Почему мой объект является указателем?

Order o1 = new Order(); 
o1.property1 = "test 1"; 

Order o2 = new Order(); 
o2 = o1; 

o1.property1 = "test 2"; 

Но в конце этого кода, как O1 и O2 имеют property1 набор «тест-2». Я думаю, что я понимаю, что все объекты являются просто указателями, поэтому, если вы меняете один, он меняет другой, но я не могу понять, почему это так, или почему это полезно. Есть ли какая-то фундаментальная вещь, которую я здесь не хватает? Кроме того, что было бы лучшим способом выполнить то, что я хочу сделать? Что: хранить состояние объекта, вносить изменения, а затем при необходимости восстанавливать. Надеюсь, это имеет смысл.

+0

См. Http://msdn.microsoft.com/en-us/library/t63sy5hs(v=vs.80).aspx для документации, которая объясняет это. – David

+1

вам нужно понять ссылочные типы и типы значений. Классы являются ссылочными типами, когда вы назначаете o1-o2, вы фактически назначаете ссылку на o1, поэтому оба о1 и o2 указывают на одно и то же место в памяти. Так C# работает со ссылочными типами (т.е. классами). –

+0

Спасибо Стэн. Ключом является назначение o2 = o1, просто назначая ссылку на объект, а не значения внутри него. – bardogodspeed

ответ

7

Переменная объекта в C# является ссылкой (не указатель) к конкретному объекту в памяти. При объявлении

Order o2 = new Order(); 

вы создаете новый объект Order в куче, и выделяя ссылку на этот объект ваших o2 переменных. Когда вы тогда указываете

o2 = o1; 

Вы говорите компилятору, чтобы сделать o2 ссылкой на o1. На этом этапе ссылка на исходный объект o2 будет потеряна, и память для этого объекта будет удалена во время следующей развертки сбора мусора.

Отныне оба o1 и o2 ссылаются на один и тот же объект в памяти. Чтобы скопировать информацию из одного объекта в другой, вам необходимо реализовать процедуру для создания экземпляра нового целевого объекта и копирования всех данных с одного объекта на другой. Дополнительную информацию см. В документах MSDN на ICloneable.

2

Это дизайн. Если вы хотите клонировать и сохранять независимый клон, я бы рекомендовал реализовать механизм клонирования для ваших типов. Это может быть ICloneable или даже просто конструктор, который принимает экземпляр и копирует значения из него.

1

Объекты по определению являются «указателями»; они содержат ссылку на ваши данные, а не на фактические данные . Вы можете присвоить ему тип значения, хотя это даст вид хранения данных.

Как было указано выше, понимание Value types vs. Reference types является ключевым.

4

Что вы имеете в виду, это разница между типами значений и ссылочными типами. Очевидно, ваш объект Order является ссылочным типом, я бы предположил, что это класс.

Классы являются ссылочными типами, что означает «указатели». Одной из причин этого является производительность, так как вы не хотите копировать огромное количество данных каждый раз, когда вы назначаете переменную.

Структуры являются типами значений и будут скопированы в память при их назначении.

У вас есть 2 решения:

  • Используйте-структуру вместо класса
  • Clone ваш объект, используя либо MemberwiseClone, если это очень просто, или использовать свой собственный метод, если вам нужно выполнить глубокий клон.
+2

, пожалуйста, не используйте структуру, если вы совершенно уверены, что понимаете разницу между ссылочными и значениями. –

1

В Java нет понятия какого-либо не примитивного типа данных, кроме ссылки на объект; так как почти все, что можно сделать с ссылкой на объект, связано с воздействием на объект, на который ссылается, таким образом, оператор . в Java. Хотя .net имеет не примитивные типы значений, большинство языков .net поддерживают соглашение (отличное от C и C++, которые используют -> для доступа к члену объекта с заостренным объектом и . для доступа к члену структуры), что тот же оператор . используется как для «разыменования и доступа», так и для «члена типа значения доступа».

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

2

Что касается вашего вопроса

что будет лучший способ сделать то, что я хочу сделать? Что: магазин состояние объекта, внести изменения, а затем возвращается в случае необходимости

Простой метод должен просто сериализовать объект, например, используя XMLSerializer. Затем, если вы хотите выбросить свои изменения, просто десериализуйте исходный объект и замените модифицированный объект на исходную версию.

2

Используйте Структуры для выполнения своей задачи, Классы являются ссылочным, а Структуры - Тип значения. Классы хранятся в куче памяти Структуры хранятся в стеке. для получения дополнительной информации Структуры против классов и изучения отличий

Смежные вопросы