Страница 370 из 502
<b>class Test : ICloneable {</b>
<b> public X o;</b>
<b> public int b;</b>
<b> public Test(int x, int y) {</b>
<b> o = new X(x);</b>
<b> b = y;</b>
<b> }</b>
<b> public void Show(string name) {</b>
<b> Console.Write("Значения объекта " + name + ": ");</b>
<b> Console.WriteLine("o.a: {0}, b: {1}", o.a, b);</b>
<b> }</b>
<b> // Создать полную копию вызывающего объекта,</b>
<b> public object Clone() {</b>
<b> Test temp = new Test(o.a, b);</b>
<b> return temp;</b>
<b> }</b>
<b>}</b>
<b>class CloneDemo {</b>
<b> static void Main() {</b>
<b> Test ob1 = new Test(10, 20);</b>
<b> ob1.Show("ob1");</b>
<b> Console.WriteLine("Сделать объект ob2 копией объекта ob1.");</b>
<b> Test ob2 = (Test)ob1.Clone();</b>
<b> ob2.Show("ob2");</b>
<b> Console.WriteLine("Изменить значение ob1.о.а на 99, " +</b>
<b> " а значение ob1.b — на 88.");</b>
<b> ob1.o.a = 99;</b>
<b> ob1.b = 88;</b>
<b> ob1.Show("ob1");</b>
<b> ob2.Show("ob2");</b>
<b> }</b>
<b>}</b>
Ниже приведен результат выполнения этой программы.
<b>Значения объекта оb1: о.а: 10, b: 20</b>
<b>Сделать объект оb2 копией объекта оb1.</b>
<b>Значения объекта оb2: о.а: 10, b: 20</b>
<b>Изменить значение ob1.о.а на 99, а значение obl.b — на 88.</b>
<b>Значения объекта оb1: о.а: 99, b: 88</b>
<b>Значения объекта оb2: о.а: 10, b: 20</b>
Как следует из результата выполнения приведенной выше программы, объект оb2 является копией объекта оb1, но это совершенно разные объекты. Изменения в одном из них не оказывают никакого влияния на другой. Это достигается конструированием нового объекта типа Test, который выделяет новый объект типа X для копирования. При этом новому экземпляру объекта типа X присваивается такое же значение, как и у объекта типа X в оригинале.
Для получения неполной копии достаточно вызвать метод MemberwiseClone(), определяемый в классе Object из метода Clone(). В качестве упражнения попробуйте заменить метод Clone() в предыдущем примере программы на следующий его вариант.
<b>// Сделать неполную копию вызывающего объекта,</b>
<b>public object Clone() {</b>
<b> Test temp = (Test) MemberwiseClone();</b>
<b> return temp;</b>
<b>}</b>
После этого изменения результат выполнения данной программы будет выглядеть следующим образом.
<b>Значения объекта ob1: о.а: 10, b: 20</b>
<b>Сделать объект оb2 копией объекта оb1.</b>
<b>Значения объекта оb2: о.а: 10, b: 20</b>
<b>Изменить значение ob1.о.а на 99, а значение obl.b — на 88.</b>
<b>Значения объекта ob1: о.а: 99, b:</b>
<b>88 Значения объекта оb2: о.а: 99, b: 20</b>
Как видите, обе переменные экземпляра о в объектах оb1 и оb2 ссылаются на один и тот же объект типа X. Поэтому изменения в одном объекте оказывают влияние на другой. Но в то же время поля b типа int в каждом из них разделены, поскольку типы значений недоступны по ссылке.
Интерфейсы IFormatProvider и IFormattable
В интерфейсе IFormatProvider определен единственный метод GetFormat(), который возвращает объект, определяющий форматирование данных в удобочитаемой форме текстовой строки. Ниже приведена общая форма метода GetFormat():
<b>object GetFormat(Type formatType)</b>
где formatType — это объект, получаемый для форматирования.
Интерфейс IFormattable поддерживает форматирование выводимых результатов в удобочитаемой форме. В нем определен следующий метод:
<b>string ToString(string format, IFormatProvider formatProvider)</b>
где format обозначает инструкции для форматирования, a formatProvider — поставщик формата.