MemberWiseClone
В программировании, как и в современной науке:
Но самое важное правило клонирования формулируется так:
Следующий пример наглядно показывает, что имеется в виду под этим предупреждением. Массивы VB .NET в отличие от массивов VB6 являются объектами.
Допустим, мы пытаемся клонировать объект класса, одно из полей которого представляет собой массив:
1 Public Class EmbeddedObjects
2 Private m_Data() As String
3 Public Sub New(ByVa1 anArray() As String)
4 m_Data = anArray
5 End Sub
6 Public Sub OisplayData()
7 Dim temp As String
8 For Each temp In m_Data
9 Console.WriteLine(temp)
10 Next
11 End Sub
12 Public Sub ChangeData(ByVal newData As String)
13 m_Data(0) = newData
14 End Sub
15 Public Function Clone() As EmbeddedObjects
16 Return CType(Me.MemberwiseClone. EmbeddedObjects)
17 End Function
18 End Class
Выполните следующую процедуру 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

Рис. 5.6. Метод MemberWiseClose не работает
Как видно из рис. 5.6, результат получился весьма неожиданным: изменения клона отражаются на исходном объекте!
Что происходит в этом примере? Почему метод MemberWiseClone не работает, как задумано? Почему изменения в объекте b отражаются на объекте а? Потому что в строках 2 и 4 класса EmbeddedObjects в качестве значения поля, задаваемого в конструкторе, используется массив. Массивы являются изменяемыми объектами; как было показано в главе 3, из этого следует, что содержимое массива может изменяться даже при передаче по значению (ByVal). Состояние внутреннего массива изменяется в строках 12-14 класса EmbeddedObjects. Поскольку объект и псевдоклон связаны ссылкой на массив m_Data, изменения клона отражаются на исходном объекте.
Решение этой проблемы рассматривается в разделе «ICloneable» этой главы. А пока мы просто укажем, что настоящий клон (иногда называемый глубокой копией) создает клоны всех полей объекта, при необходимости выполняя рекурсивное кло-нирование. Например, если одно из полей класса является объектом и содержит еще один внутренний объект, процесс клонирования должен опуститься на два уровня в глубь.
Наконец, в качестве средства дополнительной защиты разработчики .NET Framework объявили MemberWiseClone защищенным методом класса Object. Как было показано выше, это означает, что MemberWi seCI one может вызываться только из производных классов. Код за пределами производного класса не может клонировать объекты при помощи этого небезопасного метода.Также обратите внимание на то, что MemberWi seCIone возвращает тип Object, поэтому в строке 1б класса EmbeddedObjects приходится использовать функцию СТуре.