Как чтобы при копировании объектов в C# копировались данные класса, а не ссылка?
последнее обновление: 0 0
Переменная класса это переменная ссылочного типа.
Переменная ссылочного типа содержит не данные, а ссылку.
В примере переменная b2 хранит ссылку
C#
class Book
{
public string Name;
}
class Program
{
static void Main (string [] args)
{
Book b1 = new Book();
b1.name = "Book1" ;
Book b2 = b1 ; // b2 содержит ссылку на b1 поэтому:
// меняя b2.Name меняется и b1.Name
// если поменяем b1.Name то поменяется и b2.Name
b2.Name = "Book2" ;
// b1.Name "Book2"
// b2.Name "Book2"
}
}
Чтобы скопировать данные класса , а не ссылку есть 2 варианта:
Вариант 1 Реализовать интерфейс ICloneable
C#
public interface ICloneable
{
object Clone();
}
Html
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Book: ICloneable
{
public string Name;
public object Clone ()
{
return new Book() { Name = this .Name };
}
}
class Program
{
static void Main(string[] args)
{
Book b1 = new Book();
b1.Name = "Book1" ;
Book b2 = (Book)b1.Clone();
b2.Name = "Book2" ;
// b1.name "Book1"
// b2.name "Book2"
}
}
}
Вариант 2 Использовать специальный метод MemberwiseClone()
C#
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Book : ICloneable
{
public string Name;
public object Clone ()
{
return this .MemberwiseClone();
}
}
class Program
{
static void Main(string [] args)
{
Book b1 = new Book();
b1.Name = "Book1" ;
Book b2 = (Book)b1.Clone();
b2.Name = "Book2" ;
// b1.name "Book1"
// b2.name "Book2"
}
}
}
Этот метод реализует поверхностное (неглубокое) копирование.
Объекты 2-ого уровня не скопируются (будут содержать ссылку)
C#
using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace ConsoleApplication1
{
class Author
{
public int Age { get; set; }
}
class Book : ICloneable
{
public string Name { get; set; }
public Author Author { get; set; }
public object Clone ()
{
return this .MemberwiseClone ();
}
}
class Program
{
static void Main (string [] args)
{
Book b1 = new Book();
b1.Name = "Book1";
b1.Author = new Author() { Age = 38 };
Book b2 = (Book)b1.Clone ();
b2.Name = "Book2";
b2.Author.Age = 42;
// b1.name "Book1" b1.Author.Age 42
// b2.name "Book2" b2.Author.Age 42
}
}
}
Поверхностное копирование работает только для свойств, представляющих примитивные типы , но не для вложенных объектов.
Чтобы работало копирование для вложенных объектов надо применять глубокое копирование:
C#
Глубокое копирование вложенных объектов
class Author
{
public int Age { get; set; }
}
class Book : ICloneable
{
public string Name { get; set; }
public Author Author { get; set; }
public object Clone ()
{
Author author = new Author { Age = this .Author.Age };
return new Book
{
Name = this .Name,
Author = author
};
}
}
Склеить классы. Без наследования. В других языках вроде бы есть такое, в C# не найду. ответить