C# 你如何在 .NET 中做一个对象的深拷贝?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/129389/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How do you do a deep copy of an object in .NET?
提问by user18931
I want a true deep copy. In Java, this was easy, but how do you do it in C#?
我想要一个真正的深拷贝。在 Java 中,这很容易,但是在 C# 中如何做到这一点?
采纳答案by Kilhoffer
I've seen a few different approaches to this, but I use a generic utility method as such:
我已经看到了一些不同的方法,但我使用了一个通用的实用方法:
public static T DeepClone<T>(this T obj)
{
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
return (T) formatter.Deserialize(ms);
}
}
Notes:
笔记:
- Your class MUST be marked as
[Serializable]
for this to work. Your source file must include the following code:
using System.Runtime.Serialization.Formatters.Binary; using System.IO;
- 你的班级必须被标记
[Serializable]
为这样才能工作。 您的源文件必须包含以下代码:
using System.Runtime.Serialization.Formatters.Binary; using System.IO;
回答by Neil
Building on Kilhoffer's solution...
基于 Kilhoffer 的解决方案...
With C# 3.0 you can create an extension method as follows:
使用 C# 3.0,您可以创建一个扩展方法,如下所示:
public static class ExtensionMethods
{
// Deep clone
public static T DeepClone<T>(this T a)
{
using (MemoryStream stream = new MemoryStream())
{
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, a);
stream.Position = 0;
return (T) formatter.Deserialize(stream);
}
}
}
which extends any class that's been marked as [Serializable] with a DeepClone method
它使用 DeepClone 方法扩展任何被标记为 [Serializable] 的类
MyClass copy = obj.DeepClone();
回答by David Thornley
Maybe you only need a shallow copy, in that case use Object.MemberWiseClone()
.
也许你只需要一个浅拷贝,在这种情况下使用Object.MemberWiseClone()
.
There are good recommendations in the documentation for MemberWiseClone()
for strategies to deep copy: -
文档中有MemberWiseClone()
关于深度复制策略的很好的建议:-
http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx
http://msdn.microsoft.com/en-us/library/system.object.memberwiseclone.aspx
回答by Basil
public static object CopyObject(object input)
{
if (input != null)
{
object result = Activator.CreateInstance(input.GetType());
foreach (FieldInfo field in input.GetType().GetFields(Consts.AppConsts.FullBindingList))
{
if (field.FieldType.GetInterface("IList", false) == null)
{
field.SetValue(result, field.GetValue(input));
}
else
{
IList listObject = (IList)field.GetValue(result);
if (listObject != null)
{
foreach (object item in ((IList)field.GetValue(input)))
{
listObject.Add(CopyObject(item));
}
}
}
}
return result;
}
else
{
return null;
}
}
This way is a few times faster than BinarySerialization
AND this does not require the [Serializable]
attribute.
这种方式比BinarySerialization
AND 这不需要[Serializable]
属性快几倍。
回答by Contango
You can use Nested MemberwiseClone to do a deep copy. Its almost the same speed as copying a value struct, and its an order of magnitude faster than (a) reflection or (b) serialization (as described in other answers on this page).
您可以使用Nested MemberwiseClone 进行深度复制。它的速度几乎与复制值结构相同,并且比 (a) 反射或 (b) 序列化快一个数量级(如本页其他答案所述)。
Note that ifyou use Nested MemberwiseClone for a deep copy, you have to manually implement a ShallowCopy for each nested level in the class, and a DeepCopy which calls all said ShallowCopy methods to create a complete clone. This is simple: only a few lines in total, see the demo code below.
请注意,如果您将Nested MemberwiseClone 用于深层复制,则必须为类中的每个嵌套级别手动实现 ShallowCopy,以及调用所有上述 ShallowCopy 方法以创建完整克隆的 DeepCopy。这很简单:总共只有几行,请参阅下面的演示代码。
Here is the output of the code showing the relative performance difference (4.77 seconds for deep nested MemberwiseCopy vs. 39.93 seconds for Serialization). Using nested MemberwiseCopy is almost as fast as copying a struct, and copying a struct is pretty darn close to the theoretical maximum speed .NET is capable of, which is probably quite close to the speed of the same thing in C or C++ (but would have to run some equivalent benchmarks to check this claim).
这是显示相对性能差异的代码输出(深层嵌套 MemberwiseCopy 为 4.77 秒,序列化为 39.93 秒)。使用嵌套 MemberwiseCopy 几乎与复制结构一样快,并且复制结构非常接近 .NET 能够达到的理论最大速度,这可能非常接近 C 或 C++ 中相同事物的速度(但会必须运行一些等效的基准来检查此声明)。
Demo of shallow and deep copy, using classes and MemberwiseClone:
Create Bob
Bob.Age=30, Bob.Purchase.Description=Lamborghini
Clone Bob >> BobsSon
Adjust BobsSon details
BobsSon.Age=2, BobsSon.Purchase.Description=Toy car
Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:
Bob.Age=30, Bob.Purchase.Description=Lamborghini
Elapsed time: 00:00:04.7795670,30000000
Demo of shallow and deep copy, using structs and value copying:
Create Bob
Bob.Age=30, Bob.Purchase.Description=Lamborghini
Clone Bob >> BobsSon
Adjust BobsSon details:
BobsSon.Age=2, BobsSon.Purchase.Description=Toy car
Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:
Bob.Age=30, Bob.Purchase.Description=Lamborghini
Elapsed time: 00:00:01.0875454,30000000
Demo of deep copy, using class and serialize/deserialize:
Elapsed time: 00:00:39.9339425,30000000
To understand how to do a deep copy using MemberwiseCopy, here is the demo project:
要了解如何使用 MemberwiseCopy 进行深度复制,请参阅以下演示项目:
// Nested MemberwiseClone example.
// Added to demo how to deep copy a reference class.
[Serializable] // Not required if using MemberwiseClone, only used for speed comparison using serialization.
public class Person
{
public Person(int age, string description)
{
this.Age = age;
this.Purchase.Description = description;
}
[Serializable] // Not required if using MemberwiseClone
public class PurchaseType
{
public string Description;
public PurchaseType ShallowCopy()
{
return (PurchaseType)this.MemberwiseClone();
}
}
public PurchaseType Purchase = new PurchaseType();
public int Age;
// Add this if using nested MemberwiseClone.
// This is a class, which is a reference type, so cloning is more difficult.
public Person ShallowCopy()
{
return (Person)this.MemberwiseClone();
}
// Add this if using nested MemberwiseClone.
// This is a class, which is a reference type, so cloning is more difficult.
public Person DeepCopy()
{
// Clone the root ...
Person other = (Person) this.MemberwiseClone();
// ... then clone the nested class.
other.Purchase = this.Purchase.ShallowCopy();
return other;
}
}
// Added to demo how to copy a value struct (this is easy - a deep copy happens by default)
public struct PersonStruct
{
public PersonStruct(int age, string description)
{
this.Age = age;
this.Purchase.Description = description;
}
public struct PurchaseType
{
public string Description;
}
public PurchaseType Purchase;
public int Age;
// This is a struct, which is a value type, so everything is a clone by default.
public PersonStruct ShallowCopy()
{
return (PersonStruct)this;
}
// This is a struct, which is a value type, so everything is a clone by default.
public PersonStruct DeepCopy()
{
return (PersonStruct)this;
}
}
// Added only for a speed comparison.
public class MyDeepCopy
{
public static T DeepCopy<T>(T obj)
{
object result = null;
using (var ms = new MemoryStream())
{
var formatter = new BinaryFormatter();
formatter.Serialize(ms, obj);
ms.Position = 0;
result = (T)formatter.Deserialize(ms);
ms.Close();
}
return (T)result;
}
}
Then, call the demo from main:
然后,从 main 调用演示:
void MyMain(string[] args)
{
{
Console.Write("Demo of shallow and deep copy, using classes and MemberwiseCopy:\n");
var Bob = new Person(30, "Lamborghini");
Console.Write(" Create Bob\n");
Console.Write(" Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
Console.Write(" Clone Bob >> BobsSon\n");
var BobsSon = Bob.DeepCopy();
Console.Write(" Adjust BobsSon details\n");
BobsSon.Age = 2;
BobsSon.Purchase.Description = "Toy car";
Console.Write(" BobsSon.Age={0}, BobsSon.Purchase.Description={1}\n", BobsSon.Age, BobsSon.Purchase.Description);
Console.Write(" Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:\n");
Console.Write(" Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
Debug.Assert(Bob.Age == 30);
Debug.Assert(Bob.Purchase.Description == "Lamborghini");
var sw = new Stopwatch();
sw.Start();
int total = 0;
for (int i = 0; i < 100000; i++)
{
var n = Bob.DeepCopy();
total += n.Age;
}
Console.Write(" Elapsed time: {0},{1}\n", sw.Elapsed, total);
}
{
Console.Write("Demo of shallow and deep copy, using structs:\n");
var Bob = new PersonStruct(30, "Lamborghini");
Console.Write(" Create Bob\n");
Console.Write(" Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
Console.Write(" Clone Bob >> BobsSon\n");
var BobsSon = Bob.DeepCopy();
Console.Write(" Adjust BobsSon details:\n");
BobsSon.Age = 2;
BobsSon.Purchase.Description = "Toy car";
Console.Write(" BobsSon.Age={0}, BobsSon.Purchase.Description={1}\n", BobsSon.Age, BobsSon.Purchase.Description);
Console.Write(" Proof of deep copy: If BobsSon is a true clone, then adjusting BobsSon details will not affect Bob:\n");
Console.Write(" Bob.Age={0}, Bob.Purchase.Description={1}\n", Bob.Age, Bob.Purchase.Description);
Debug.Assert(Bob.Age == 30);
Debug.Assert(Bob.Purchase.Description == "Lamborghini");
var sw = new Stopwatch();
sw.Start();
int total = 0;
for (int i = 0; i < 100000; i++)
{
var n = Bob.DeepCopy();
total += n.Age;
}
Console.Write(" Elapsed time: {0},{1}\n", sw.Elapsed, total);
}
{
Console.Write("Demo of deep copy, using class and serialize/deserialize:\n");
int total = 0;
var sw = new Stopwatch();
sw.Start();
var Bob = new Person(30, "Lamborghini");
for (int i = 0; i < 100000; i++)
{
var BobsSon = MyDeepCopy.DeepCopy<Person>(Bob);
total += BobsSon.Age;
}
Console.Write(" Elapsed time: {0},{1}\n", sw.Elapsed, total);
}
Console.ReadKey();
}
Again, note that ifyou use Nested MemberwiseClone for a deep copy, you have to manually implement a ShallowCopy for each nested level in the class, and a DeepCopy which calls all said ShallowCopy methods to create a complete clone. This is simple: only a few lines in total, see the demo code above.
再次注意,如果您使用Nested MemberwiseClone 进行深层复制,则必须为类中的每个嵌套级别手动实现 ShallowCopy,以及调用所有上述 ShallowCopy 方法以创建完整克隆的 DeepCopy。这很简单:总共只有几行,参见上面的演示代码。
Note that when it comes to cloning an object, there is is a big difference between a "struct" and a "class":
请注意,在克隆对象时,“结构”和“类”之间存在很大差异:
- If you have a "struct", it's a value type so you can just copy it, and the contents will be cloned.
- If you have a "class", it's a reference type, so if you copy it, all you are doing is copying the pointer to it. To create a true clone, you have to be more creative, and use a method which creates another copy of the original object in memory.
- Cloning objects incorrectly can lead to very difficult-to-pin-down bugs. In production code, I tend to implement a checksum to double check that the object has been cloned properly, and hasn't been corrupted by another reference to it. This checksum can be switched off in Release mode.
- I find this method quite useful: often, you only want to clone parts of the object, not the entire thing. It's also essential for any use case where you are modifying objects, then feeding the modified copies into a queue.
- 如果你有一个“结构”,它是一个值类型,所以你可以复制它,内容将被克隆。
- 如果你有一个“类”,它是一个引用类型,所以如果你复制它,你所做的就是复制指向它的指针。要创建真正的克隆,您必须更有创意,并使用一种方法在内存中创建原始对象的另一个副本。
- 错误地克隆对象会导致非常难以确定的错误。在生产代码中,我倾向于实现一个校验和来仔细检查对象是否已正确克隆,并且没有被另一个引用损坏。此校验和可以在发布模式下关闭。
- 我发现这种方法非常有用:通常,您只想克隆对象的一部分,而不是整个对象。对于修改对象然后将修改后的副本送入队列的任何用例来说,这也是必不可少的。
Update
更新
It's probably possible to use reflection to recursively walk through the object graph to do a deep copy. WCF uses this technique to serialize an object, including all of its children. The trick is to annotate all of the child objects with an attribute that makes it discoverable. You might lose some performance benefits, however.
可能可以使用反射来递归遍历对象图以进行深度复制。WCF 使用这种技术来序列化一个对象,包括它的所有子对象。诀窍是用一个属性来注释所有子对象,使其可被发现。但是,您可能会失去一些性能优势。
Update
更新
Quote on independent speed test (see comments below):
引用独立速度测试(见下面的评论):
I've run my own speed test using Neil's serialize/deserialize extension method, Contango's Nested MemberwiseClone, Alex Burtsev's reflection-based extension method and AutoMapper, 1 million times each. Serialize-deserialize was slowest, taking 15.7 seconds. Then came AutoMapper, taking 10.1 seconds. Much faster was the reflection-based method which took 2.4 seconds. By far the fastest was Nested MemberwiseClone, taking 0.1 seconds. Comes down to performance versus hassle of adding code to each class to clone it. If performance isn't an issue go with Alex Burtsev's method. – Simon Tewsi
我已经使用 Neil 的序列化/反序列化扩展方法、Contango 的 Nested MemberwiseClone、Alex Burtsev 的基于反射的扩展方法和 AutoMapper 运行了我自己的速度测试,各进行了 100 万次。Serialize-deserialize 最慢,需要 15.7 秒。然后是 AutoMapper,耗时 10.1 秒。基于反射的方法要快得多,需要 2.4 秒。目前最快的是 Nested MemberwiseClone,耗时 0.1 秒。归结为性能与向每个类添加代码以克隆它的麻烦。如果性能不是问题,请使用 Alex Burtsev 的方法。– 西蒙·图西
回答by Kurt Richardson
I believe that the BinaryFormatter approach is relatively slow (which came as a surprise to me!). You might be able to use ProtoBuf .NET for some objects if they meet the requirements of ProtoBuf. From the ProtoBuf Getting Started page (http://code.google.com/p/protobuf-net/wiki/GettingStarted):
我相信 BinaryFormatter 方法相对较慢(这让我感到惊讶!)。如果某些对象满足 ProtoBuf 的要求,您也许可以将它们使用 ProtoBuf .NET。从 ProtoBuf 入门页面 ( http://code.google.com/p/protobuf-net/wiki/GettingStarted):
Notes on types supported:
关于支持的类型的说明:
Custom classes that:
自定义类:
- Are marked as data-contract
- Have a parameterless constructor
- For Silverlight: are public
- Many common primitives, etc.
- Singledimension arrays: T[]
- List<T> / IList<T>
- Dictionary<TKey, TValue> / IDictionary<TKey, TValue>
- any type which implements IEnumerable<T> and has an Add(T) method
- 被标记为数据契约
- 有一个无参数的构造函数
- 对于 Silverlight:是公开的
- 许多常见的原语等。
- 一维数组:T[]
- 列表<T> / IList<T>
- 字典<TKey, TValue> / IDictionary<TKey, TValue>
- 任何实现 IEnumerable<T> 并具有 Add(T) 方法的类型
The code assumes that types will be mutable around the elected members. Accordingly, custom structs are not supported, since they should be immutable.
The code assumes that types will be mutable around the elected members. 因此,不支持自定义结构,因为它们应该是不可变的。
If your class meets these requirements you could try:
如果您的课程满足这些要求,您可以尝试:
public static void deepCopy<T>(ref T object2Copy, ref T objectCopy)
{
using (var stream = new MemoryStream())
{
Serializer.Serialize(stream, object2Copy);
stream.Position = 0;
objectCopy = Serializer.Deserialize<T>(stream);
}
}
Which is VERY fast indeed...
这确实非常快......
Edit:
编辑:
Here is working code for a modification of this (tested on .NET 4.6). It uses System.Xml.Serialization and System.IO. No need to mark classes as serializable.
这是对此进行修改的工作代码(在 .NET 4.6 上测试)。它使用 System.Xml.Serialization 和 System.IO。无需将类标记为可序列化。
public void DeepCopy<T>(ref T object2Copy, ref T objectCopy)
{
using (var stream = new MemoryStream())
{
var serializer = new XS.XmlSerializer(typeof(T));
serializer.Serialize(stream, object2Copy);
stream.Position = 0;
objectCopy = (T)serializer.Deserialize(stream);
}
}
回答by Suresh Kumar Veluswamy
You can try this
你可以试试这个
public static object DeepCopy(object obj)
{
if (obj == null)
return null;
Type type = obj.GetType();
if (type.IsValueType || type == typeof(string))
{
return obj;
}
else if (type.IsArray)
{
Type elementType = Type.GetType(
type.FullName.Replace("[]", string.Empty));
var array = obj as Array;
Array copied = Array.CreateInstance(elementType, array.Length);
for (int i = 0; i < array.Length; i++)
{
copied.SetValue(DeepCopy(array.GetValue(i)), i);
}
return Convert.ChangeType(copied, obj.GetType());
}
else if (type.IsClass)
{
object toret = Activator.CreateInstance(obj.GetType());
FieldInfo[] fields = type.GetFields(BindingFlags.Public |
BindingFlags.NonPublic | BindingFlags.Instance);
foreach (FieldInfo field in fields)
{
object fieldValue = field.GetValue(obj);
if (fieldValue == null)
continue;
field.SetValue(toret, DeepCopy(fieldValue));
}
return toret;
}
else
throw new ArgumentException("Unknown type");
}
Thanks to DetoX83 articleon code project.
感谢 DetoX83关于代码项目的文章。
回答by alex
The best way is:
最好的办法是:
public interface IDeepClonable<T> where T : class
{
T DeepClone();
}
public class MyObj : IDeepClonable<MyObj>
{
public MyObj Clone()
{
var myObj = new MyObj();
myObj._field1 = _field1;//value type
myObj._field2 = _field2;//value type
myObj._field3 = _field3;//value type
if (_child != null)
{
myObj._child = _child.DeepClone(); //reference type .DeepClone() that does the same
}
int len = _array.Length;
myObj._array = new MyObj[len]; // array / collection
for (int i = 0; i < len; i++)
{
myObj._array[i] = _array[i];
}
return myObj;
}
private bool _field1;
public bool Field1
{
get { return _field1; }
set { _field1 = value; }
}
private int _field2;
public int Property2
{
get { return _field2; }
set { _field2 = value; }
}
private string _field3;
public string Property3
{
get { return _field3; }
set { _field3 = value; }
}
private MyObj _child;
private MyObj Child
{
get { return _child; }
set { _child = value; }
}
private MyObj[] _array = new MyObj[4];
}
回答by Alex Burtsev
I wrote a deep object copy extension method, based on recursive "MemberwiseClone". It is fast (three times fasterthan BinaryFormatter), and it works with any object. You don't need a default constructor or serializable attributes.
我写了一个基于递归“MemberwiseClone”的深层对象复制扩展方法。它很快(比 BinaryFormatter快三倍),并且适用于任何对象。您不需要默认构造函数或可序列化属性。
Source code:
源代码:
using System.Collections.Generic;
using System.Reflection;
using System.ArrayExtensions;
namespace System
{
public static class ObjectExtensions
{
private static readonly MethodInfo CloneMethod = typeof(Object).GetMethod("MemberwiseClone", BindingFlags.NonPublic | BindingFlags.Instance);
public static bool IsPrimitive(this Type type)
{
if (type == typeof(String)) return true;
return (type.IsValueType & type.IsPrimitive);
}
public static Object Copy(this Object originalObject)
{
return InternalCopy(originalObject, new Dictionary<Object, Object>(new ReferenceEqualityComparer()));
}
private static Object InternalCopy(Object originalObject, IDictionary<Object, Object> visited)
{
if (originalObject == null) return null;
var typeToReflect = originalObject.GetType();
if (IsPrimitive(typeToReflect)) return originalObject;
if (visited.ContainsKey(originalObject)) return visited[originalObject];
if (typeof(Delegate).IsAssignableFrom(typeToReflect)) return null;
var cloneObject = CloneMethod.Invoke(originalObject, null);
if (typeToReflect.IsArray)
{
var arrayType = typeToReflect.GetElementType();
if (IsPrimitive(arrayType) == false)
{
Array clonedArray = (Array)cloneObject;
clonedArray.ForEach((array, indices) => array.SetValue(InternalCopy(clonedArray.GetValue(indices), visited), indices));
}
}
visited.Add(originalObject, cloneObject);
CopyFields(originalObject, visited, cloneObject, typeToReflect);
RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect);
return cloneObject;
}
private static void RecursiveCopyBaseTypePrivateFields(object originalObject, IDictionary<object, object> visited, object cloneObject, Type typeToReflect)
{
if (typeToReflect.BaseType != null)
{
RecursiveCopyBaseTypePrivateFields(originalObject, visited, cloneObject, typeToReflect.BaseType);
CopyFields(originalObject, visited, cloneObject, typeToReflect.BaseType, BindingFlags.Instance | BindingFlags.NonPublic, info => info.IsPrivate);
}
}
private static void CopyFields(object originalObject, IDictionary<object, object> visited, object cloneObject, Type typeToReflect, BindingFlags bindingFlags = BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.FlattenHierarchy, Func<FieldInfo, bool> filter = null)
{
foreach (FieldInfo fieldInfo in typeToReflect.GetFields(bindingFlags))
{
if (filter != null && filter(fieldInfo) == false) continue;
if (IsPrimitive(fieldInfo.FieldType)) continue;
var originalFieldValue = fieldInfo.GetValue(originalObject);
var clonedFieldValue = InternalCopy(originalFieldValue, visited);
fieldInfo.SetValue(cloneObject, clonedFieldValue);
}
}
public static T Copy<T>(this T original)
{
return (T)Copy((Object)original);
}
}
public class ReferenceEqualityComparer : EqualityComparer<Object>
{
public override bool Equals(object x, object y)
{
return ReferenceEquals(x, y);
}
public override int GetHashCode(object obj)
{
if (obj == null) return 0;
return obj.GetHashCode();
}
}
namespace ArrayExtensions
{
public static class ArrayExtensions
{
public static void ForEach(this Array array, Action<Array, int[]> action)
{
if (array.LongLength == 0) return;
ArrayTraverse walker = new ArrayTraverse(array);
do action(array, walker.Position);
while (walker.Step());
}
}
internal class ArrayTraverse
{
public int[] Position;
private int[] maxLengths;
public ArrayTraverse(Array array)
{
maxLengths = new int[array.Rank];
for (int i = 0; i < array.Rank; ++i)
{
maxLengths[i] = array.GetLength(i) - 1;
}
Position = new int[array.Rank];
}
public bool Step()
{
for (int i = 0; i < Position.Length; ++i)
{
if (Position[i] < maxLengths[i])
{
Position[i]++;
for (int j = 0; j < i; j++)
{
Position[j] = 0;
}
return true;
}
}
return false;
}
}
}
}
回答by Jordan Morris
I have a simpler idea. Use LINQ with a new selection.
我有一个更简单的想法。将 LINQ 与新选择一起使用。
public class Fruit
{
public string Name {get; set;}
public int SeedCount {get; set;}
}
void SomeMethod()
{
List<Fruit> originalFruits = new List<Fruit>();
originalFruits.Add(new Fruit {Name="Apple", SeedCount=10});
originalFruits.Add(new Fruit {Name="Banana", SeedCount=0});
//Deep Copy
List<Fruit> deepCopiedFruits = from f in originalFruits
select new Fruit {Name=f.Name, SeedCount=f.SeedCount};
}