Похоже, вам нужно установить ссылку на:
glfw.lib
opengl32.lib
. Стоит прочитать примечания к выпуску: здесь
Пока общепринятая практика должна реализовать ICloneable
интерфейс (описал здесь , таким образом, я не извергну), вот хорошее глубокое копировальное устройство объекта клона, которое я нашел на Проект Кода только что и включил его в наш материал.
, Как упомянуто в другом месте, это действительно требует Вашим объектам быть сериализуемым.
using System;
using System.IO;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
/// <summary>
/// Reference Article http://www.codeproject.com/KB/tips/SerializedObjectCloner.aspx
/// Provides a method for performing a deep copy of an object.
/// Binary Serialization is used to perform the copy.
/// </summary>
public static class ObjectCopier
{
/// <summary>
/// Perform a deep Copy of the object.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T Clone<T>(T source)
{
if (!typeof(T).IsSerializable)
{
throw new ArgumentException("The type must be serializable.", nameof(source));
}
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
IFormatter formatter = new BinaryFormatter();
Stream stream = new MemoryStream();
using (stream)
{
formatter.Serialize(stream, source);
stream.Seek(0, SeekOrigin.Begin);
return (T)formatter.Deserialize(stream);
}
}
}
идея состоит в том, что это сериализирует Ваш объект и затем десериализовывает его в новый объект. Преимущество - то, что Вы не должны интересоваться о клонировании всего, когда объект становится слишком сложным.
И с использованием дополнительных методов (также из источника, на который первоначально ссылаются):
В случае, если Вы предпочитаете использовать новое дополнительные методы из C# 3.0, измените метод для имения следующей подписи:
public static T Clone<T>(this T source)
{
//...
}
Теперь вызов метода просто становится objectBeingCloned.Clone();
.
РЕДАКТИРОВАНИЕ (10 января 2015) Мысль я пересмотрел бы это, чтобы упомянуть, что я недавно начал использовать (Newtonsoft) Json, чтобы сделать это, это должно быть легче и избегает издержек [сериализуемых] тегов. ( NB @atconway указал в комментариях, что члены парламента, не занимающие официального поста не клонированы с помощью метода JSON)
/// <summary>
/// Perform a deep Copy of the object, using Json as a serialisation method. NOTE: Private members are not cloned using this method.
/// </summary>
/// <typeparam name="T">The type of object being copied.</typeparam>
/// <param name="source">The object instance to copy.</param>
/// <returns>The copied object.</returns>
public static T CloneJson<T>(this T source)
{
// Don't serialize a null object, simply return the default for that object
if (Object.ReferenceEquals(source, null))
{
return default(T);
}
// initialize inner objects individually
// for example in default constructor some list property initialized with some values,
// but in 'source' these items are cleaned -
// without ObjectCreationHandling.Replace default constructor values will be added to result
var deserializeSettings = new JsonSerializerSettings {ObjectCreationHandling = ObjectCreationHandling.Replace};
return JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source), deserializeSettings);
}
Аплодисменты.
Я предпочитаю конструктора копии клону. Намерение более ясно.
В целом Вы реализуете интерфейс ICloneable и реализуете, Клонируют себя. Объекты C# имеют встроенный метод MemberwiseClone, который выполняет мелкую копию, которая может выручить Вас для всех примитивов.
Для глубокой копии, нет никакого способа, которым она может знать, как автоматически сделать это.
Причина не использовать ICloneable не , потому что это не имеет универсального интерфейса. причина не использовать его состоит в том, потому что это неопределенно . Это не ясно дает понять, получаете ли Вы отмель или глубокую копию; это до лица, осуществляющего внедрение.
Да, MemberwiseClone
делает мелкую копию, но противоположность MemberwiseClone
не Clone
; это было бы, возможно, DeepClone
, который не существует. При использовании объекта через его интерфейс ICloneable Вы не можете знать, какой вид клонирования основного объекта работает. (И XML-комментарии не прояснят, потому что Вы получите интерфейсные комментарии, а не тех на методе Клона объекта.)
то, Что я обычно делаю, просто делают Copy
метод, который делает точно, что я хочу.
Короткий ответ - Вы, наследовались интерфейсу ICloneable и затем реализуют функцию .clone. Клон должен сделать копию memberwise и выполнить глубокую копию на любом участнике, который требует его, затем возвратите полученный объект. Это - рекурсивная операция (она требует, чтобы все члены класса, который Вы хотите клонировать, были или типами значения или реализовали ICloneable и что их участники являются или типами значения или реализуют ICloneable, и так далее).
Для более подробного объяснения при Клонировании использования ICloneable, проверьте эта статья .
длинный , ответ, "это зависит". Как упомянуто другими, ICloneable не поддерживается дженериками, требует специальных замечаний для круговых ссылок класса и на самом деле просматривается некоторыми как "ошибка" в Платформе.NET. Метод сериализации зависит от Ваших объектов, являющихся сериализуемым, которым они не могут быть, и Вы не можете иметь никакого контроля. Существует все еще много дебатов в сообществе, по которому "лучшая" практика. В действительности ни одно из решений не единая лучшая практика для всех ситуаций как ICloneable, первоначально интерпретировался, чтобы быть.
Посмотрите этот статья Corner Разработчика еще для нескольких опций (кредит Ian).
Я придумал это, чтобы преодолеть недостаток .NET , когда нужно вручную копировать List
Я использую это:
static public IEnumerable<SpotPlacement> CloneList(List<SpotPlacement> spotPlacements)
{
foreach (SpotPlacement sp in spotPlacements)
{
yield return (SpotPlacement)sp.Clone();
}
}
И в другое место:
public object Clone()
{
OrderItem newOrderItem = new OrderItem();
...
newOrderItem._exactPlacements.AddRange(SpotPlacement.CloneList(_exactPlacements));
...
return newOrderItem;
}
Я попытался придумать один лайнер, который делает это, но это невозможно из-за того, что yield не работает внутри блоков анонимных методов.
Еще лучше, используйте общий клонер List
class Utility<T> where T : ICloneable
{
static public IEnumerable<T> CloneList(List<T> tl)
{
foreach (T t in tl)
{
yield return (T)t.Clone();
}
}
}
Что ж, у меня были проблемы с использованием ICloneable в Silverlight, но мне понравилась идея серализации, я могу серализовать XML, поэтому я сделал следующее:
static public class SerializeHelper
{
//Michael White, Holly Springs Consulting, 2009
//michael@hollyspringsconsulting.com
public static T DeserializeXML<T>(string xmlData) where T:new()
{
if (string.IsNullOrEmpty(xmlData))
return default(T);
TextReader tr = new StringReader(xmlData);
T DocItms = new T();
XmlSerializer xms = new XmlSerializer(DocItms.GetType());
DocItms = (T)xms.Deserialize(tr);
return DocItms == null ? default(T) : DocItms;
}
public static string SeralizeObjectToXML<T>(T xmlObject)
{
StringBuilder sbTR = new StringBuilder();
XmlSerializer xmsTR = new XmlSerializer(xmlObject.GetType());
XmlWriterSettings xwsTR = new XmlWriterSettings();
XmlWriter xmwTR = XmlWriter.Create(sbTR, xwsTR);
xmsTR.Serialize(xmwTR,xmlObject);
return sbTR.ToString();
}
public static T CloneObject<T>(T objClone) where T:new()
{
string GetString = SerializeHelper.SeralizeObjectToXML<T>(objClone);
return SerializeHelper.DeserializeXML<T>(GetString);
}
}
Правовая оговорка: я - автор упомянутого пакета.
я был удивлен, как главные ответы на этот вопрос в 2019 все еще используют сериализацию или отражение.
BinaryFormatter
, требует эти Serializable
, атрибут, JsonConverter
требует конструктора без параметров или атрибутов, никакой дескриптор поля только для чтения или взаимодействует через интерфейс очень хорошо, и оба 10-30x медленнее, чем необходимый.
можно вместо этого использовать Деревья выражений или Отражение. Испустите , чтобы сгенерировать клонирующийся код только однажды, затем использовать тот скомпилированный код вместо медленного отражения или сериализации.
сталкивавшийся с проблемой самостоятельно и видящий удовлетворительное решение, я решил создать пакет, который делает просто это и работы с каждым типом и является почти с такой скоростью, как пользовательский написанный код .
можно найти проект на GitHub: https://использование github.com/marcelltoth/ObjectCloner
можно установить его от NuGet. Любой получает ObjectCloner
пакет и использует его как:
var clone = ObjectCloner.DeepClone(original);
или если Вы не возражаете загрязнять свой тип объекта расширениями, добираются ObjectCloner.Extensions
также и запись:
var clone = original.DeepClone();
А простой сравнительный тест клонирования иерархии классов показал производительность ~3x быстрее, чем использование Отражения, ~12x быстрее, чем Newtonsoft. Сериализация Json и ~36x быстрее, чем высоко предложенный BinaryFormatter
.
Самый короткий путь, но зависимость от потребности:
using Newtonsoft.Json;
public static T Clone<T>(T source) =>
JsonConvert.DeserializeObject<T>(JsonConvert.SerializeObject(source));