Создать копию объекта
Мне нужно клонировать объект (класс, а не структура) в.net 4.5 (C#).
Я нашел два пути:
- Реализация интерфейса ICloneable
- Создайте собственный механизм клонирования, как этот известный ответ SO
Мне нравится первый способ - это проще, но я также обнаружил интерфейс Not Implpement ICloneable, но это очень старая статья, и в MSDN я не могу найти, что этот интерфейс устарел.
Может ли кто-нибудь сказать мне, это безопасно использовать ICloneable в.net 4.5?
2 ответа
Вы не должны использовать интерфейс IClonable.
Вот блог Брэда Абрамса, в котором обсуждается, почему не несколько лет назад. В основном, причины изложены в ответе Тима Шмельтера, но этот блог из уст лошади.
Что касается реализации клонирования с помощью сериализации, то теперь есть несколько лучший способ, потому что мы можем указать StreamingContextStates.Clone
чтобы клонирование работало лучше с такими вещами, как неуправляемые ручки.
В "CLR via C# 4 Edition" Джеффри Рихтера есть каноническая реализация, которая выглядит так:
public static object DeepClone(object original)
{
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter
{
Context = new StreamingContext(StreamingContextStates.Clone)
};
formatter.Serialize(stream, original);
stream.Position = 0;
return formatter.Deserialize(stream);
}
}
Или строго типизированный вариант:
public static T DeepClone<T>(T original)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", "original");
}
if (ReferenceEquals(original, null))
{
return default(T);
}
using (var stream = new MemoryStream())
{
var formatter = new BinaryFormatter
{
Context = new StreamingContext(StreamingContextStates.Clone)
};
formatter.Serialize(stream, original);
stream.Position = 0;
return (T) formatter.Deserialize(stream);
}
}
Я считаю, что вы должны использовать это (где это возможно) вместо реализации IClonable
,
IClonable
это просто интерфейс, поэтому он ничего не делает, пока вы его не реализуете. Пост, который предлагает не использовать IClonable
упоминает почему: не ясно, если Clone
реализуется как глубокая или как мелкая копия.
Так что просто предоставьте Copy
или же DeepClone
метод, и все знают, что происходит.
Цитата, чтобы объяснить два термина:
Существует два основных способа реализации ICloneable, как в глубоком, так и в не глубоком копировании. Deep-copy копирует клонированный объект и все объекты, на которые ссылается объект, рекурсивно, пока все объекты в графе не будут скопированы. Неглубокая копия (называемая мелкой, если копируются только ссылки верхнего уровня) не может делать ничего или является частью глубокой копии.