Чтение онлайн

ЖАНРЫ

Язык программирования C#9 и платформа .NET5
Шрифт:

{

public int X { get; set; }

public int Y { get; set; }

public PointDescription desc = new PointDescription;

public Point(int xPos, int yPos, string petName)

{

X = xPos; Y = yPos;

desc.PetName = petName;

}

public Point(int xPos, int yPos)

{

X = xPos; Y = yPos;

}

public Point { }

//
Переопределить Object.ToString.

public override string ToString

=> $"X = {X}; Y = {Y}; Name = {desc.PetName};\nID = {desc.PointID}\n";

// Возвратить копию текущего объекта.

public object Clone => this.MemberwiseClone;

}

Обратите внимание, что метод

Clone
пока еще не обновлялся. Следовательно, когда пользователь объекта запросит клонирование с применением текущей реализации, будет создана поверхностная (почленная) копия. В целях иллюстрации модифицируйте вызывающий код, как показано ниже:

Console.WriteLine("***** Fun with Object Cloning *****\n");

...

Console.WriteLine("Cloned p3 and stored new Point in p4");

Point p3 = new Point(100, 100, "Jane");

Point p4 = (Point)p3.Clone;

Console.WriteLine("Before modification:"); // Перед модификацией

Console.WriteLine("p3: {0}", p3);

Console.WriteLine("p4: {0}", p4);

p4.desc.PetName = "My new Point";

p4.X = 9;

Console.WriteLine("\nChanged p4.desc.petName and p4.X");

Console.WriteLine("After modification:"); // После модификации

Console.WriteLine("p3: {0}", p3);

Console.WriteLine("p4: {0}", p4);

Console.ReadLine;

В приведенном далее выводе видно, что хотя типы значений действительно были изменены, внутренние ссылочные типы поддерживают одни и те же значения, т.к. они "указывают" на те же самые объекты в памяти (в частности, оба объекта имеют дружественное имя

Му new Point
):

***** Fun with Object Cloning *****

Cloned p3 and stored new Point in p4

Before modification:

p3: X = 100; Y = 100; Name = Jane;

ID = 133d66a7-0837-4bd7-95c6-b22ab0434509

p4: X = 100; Y = 100; Name = Jane;

ID = 133d66a7-0837-4bd7-95c6-b22ab0434509

Changed p4.desc.petName and p4.X

After modification:

p3: X = 100; Y = 100; Name = My new Point;

ID = 133d66a7-0837-4bd7-95c6-b22ab0434509

p4: X = 9; Y = 100; Name = My new Point;

ID = 133d66a7-0837-4bd7-95c6-b22ab0434509

Чтобы заставить метод

Clone
создавать полную глубокую копию внутренних ссылочных типов, нужно сконфигурировать объект, возвращаемый методом
MemberwiseClone
, для учета имени текущего объекта
Point
(тип
System.Guid
на самом деле является структурой, так что числовые данные будут действительно копироваться). Вот одна из возможных реализаций:

// Теперь необходимо скорректировать код для учета члена.

public object Clone

{

// Сначала получить поверхностную копию.

Point newPoint = (Point)this.MemberwiseClone;

// Затем восполнить пробелы.

PointDescription currentDesc = new PointDescription;

currentDesc.PetName = this.desc.PetName;

newPoint.desc = currentDesc;

return newPoint;

}

Если снова запустить приложение и просмотреть его вывод (показанный далее), то будет видно, что возвращаемый методом

Clone
объект
Point
действительно копирует свои внутренние переменные-члены ссылочного типа (обратите внимание, что дружественные имена у
рЗ
и
р4
теперь уникальны):

***** Fun with Object Cloning *****

Cloned p3 and stored new Point in p4

Before modification:

p3: X = 100; Y = 100; Name = Jane;

ID = 51f64f25-4b0e-47ac-ba35-37d263496406

p4: X = 100; Y = 100; Name = Jane;

ID = 0d3776b3-b159-490d-b022-7f3f60788e8a

Changed p4.desc.petName and p4.X

After modification:

p3: X = 100; Y = 100; Name = Jane;

ID = 51f64f25-4b0e-47ac-ba35-37d263496406

p4: X = 9; Y = 100; Name = My new Point;

ID = 0d3776b3-b159-490d-b022-7f3f60788e8a

Давайте подведем итоги по процессу клонирования. При наличии класса или структуры, которая содержит только типы значений, необходимо реализовать метод

Clone
с использованием метода
MemberwiseClone
. Однако если есть специальный тип, поддерживающий ссылочные типы, тогда для построения глубокой копии может потребоваться создать новый объект, который учитывает каждую переменную-член ссылочного типа.

Интерфейс IComparable

Интерфейс

System.IComparable
описывает поведение, которое позволяет сортировать объекты на основе указанного ключа. Вот его формальное определение:

// Данный интерфейс позволяет объекту указывать

// его отношение с другими подобными объектами

public interface IComparable

{

int CompareTo(object o);

}

Поделиться с друзьями: