Иллюстрированный самоучитель по Visual Basic .NET

MemberWiseClone

Выполните следующую процедуру Sub Main:

Sub Main()
Dim anArray() As String ={"HELLO"}
Dim a As New EmbeddedObjects(anArray)
Console.WriteLinet"Am going to display the data in object a now!")
a.DisplayData()
Dim b As EmbeddedObjects
b =a.Clone()
Dim newData As String ="GOODBYE"
b.ChangeData(newData)
Console.WriteLine("Am going to display the data in object b now!")
b.DisplayData()
Console.WriteLine("Am going to re-display the data in a" & _
"after making a change to object b!!!") a.DisplayData()
Console. ReadLine()
End Sub

Иллюстрированный самоучитель по Visual Basic .NET › Наследование и интерфейсы › MemberWiseClone
Рис. 5.6. Метод MemberWiseClose не работает

Как видно из рис. 5.6, результат получился весьма неожиданным: изменения клона отражаются на исходном объекте!

Что происходит в этом примере? Почему метод MemberWiseClone не работает, как задумано? Почему изменения в объекте b отражаются на объекте а? Потому что в строках 2 и 4 класса EmbeddedObjects в качестве значения поля, задаваемого в конструкторе, используется массив. Массивы являются изменяемыми объектами; как было показано в главе 3, из этого следует, что содержимое массива может изменяться даже при передаче по значению (ByVal). Состояние внутреннего массива изменяется в строках 12-14 класса EmbeddedObjects. Поскольку объект и псевдоклон связаны ссылкой на массив m_Data, изменения клона отражаются на исходном объекте.

Решение этой проблемы рассматривается в разделе "ICloneable" этой главы. А пока мы просто укажем, что настоящий клон (иногда называемый глубокой копией) создает клоны всех полей объекта, при необходимости выполняя рекурсивное клонирование. Например, если одно из полей класса является объектом и содержит еще один внутренний объект, процесс клонирования должен опуститься на два уровня в глубь.

Примечание
Также существует хитроумная методика клонирования, основанная на сериализации объектов. Подробности приведены в главе 9
.

Наконец, в качестве средства дополнительной защиты разработчики .NET Framework объявили MemberWiseClone защищенным методом класса Object. Как было показано выше, это означает, что MemberWiseCI one может вызываться только из производных классов. Код за пределами производного класса не может клонировать объекты при помощи этого небезопасного метода. Также обратите внимание на то, что MemberWiseCIone возвращает тип Object, поэтому в строке 1б класса EmbeddedObjects приходится использовать функцию СType.

Если Вы заметили ошибку, выделите, пожалуйста, необходимый текст и нажмите CTRL + Enter, чтобы сообщить об этом редактору.