ฉันมีพจนานุกรมทั่วไปDictionary<string, T>
ที่ฉันต้องการสร้าง Clone () ของ .. ข้อเสนอแนะใด ๆ
ฉันมีพจนานุกรมทั่วไปDictionary<string, T>
ที่ฉันต้องการสร้าง Clone () ของ .. ข้อเสนอแนะใด ๆ
คำตอบ:
ตกลงคำตอบ. NET 2.0:
หากคุณไม่จำเป็นต้องทำการโคลนนิ่งค่าคุณสามารถใช้ Constructor Overload เพื่อ Dictionary ซึ่งใช้ IDictionary ที่มีอยู่ (คุณสามารถระบุเครื่องมือเปรียบเทียบเป็นพจนานุกรมเปรียบเทียบที่มีอยู่ได้เช่นกัน)
หากคุณไม่จำเป็นต้องโคลนค่าที่คุณสามารถใช้อะไรเช่นนี้
public static Dictionary<TKey, TValue> CloneDictionaryCloningValues<TKey, TValue>
(Dictionary<TKey, TValue> original) where TValue : ICloneable
{
Dictionary<TKey, TValue> ret = new Dictionary<TKey, TValue>(original.Count,
original.Comparer);
foreach (KeyValuePair<TKey, TValue> entry in original)
{
ret.Add(entry.Key, (TValue) entry.Value.Clone());
}
return ret;
}
แน่นอนว่าต้องอาศัยTValue.Clone()
การโคลนนิ่งที่ลึกล้ำเช่นกัน
Clone()
วิธีการไม่ว่าจะลึกหรือตื้น ฉันได้เพิ่มบันทึกย่อลงในเอฟเฟกต์นั้นแล้ว
ConcurrentDictionary
หากคุณต้องการความปลอดภัยหัวข้อเมื่อใช้พจนานุกรมการใช้งาน
(หมายเหตุ: แม้ว่ารุ่นโคลนอาจมีประโยชน์สำหรับการคัดลอกตื้น ๆ ตัวสร้างที่ฉันพูดถึงในโพสต์อื่น ๆ เป็นตัวเลือกที่ดีกว่า)
คุณต้องการให้สำเนาลึกแค่ไหนและคุณใช้. NET รุ่นใด ฉันสงสัยว่า LINQ โทรไปที่ ToDictionary โดยระบุทั้งตัวเลือกคีย์และองค์ประกอบจะเป็นวิธีที่ง่ายที่สุดถ้าคุณใช้. NET 3.5
ตัวอย่างเช่นหากคุณไม่คำนึงถึงคุณค่าที่เป็นโคลนตื้น:
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
entry => entry.Value);
หากคุณได้บังคับให้ T ใช้งาน ICloneable แล้ว:
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
entry => (T) entry.Value.Clone());
(สิ่งเหล่านี้ยังไม่ได้ทดสอบ แต่ควรใช้งานได้)
Dictionary<string, int> dictionary = new Dictionary<string, int>();
Dictionary<string, int> copy = new Dictionary<string, int>(dictionary);
สำหรับ. NET 2.0 คุณสามารถใช้คลาสที่สืบทอดDictionary
และใช้งานICloneable
ได้
public class CloneableDictionary<TKey, TValue> : Dictionary<TKey, TValue> where TValue : ICloneable
{
public IDictionary<TKey, TValue> Clone()
{
CloneableDictionary<TKey, TValue> clone = new CloneableDictionary<TKey, TValue>();
foreach (KeyValuePair<TKey, TValue> pair in this)
{
clone.Add(pair.Key, (TValue)pair.Value.Clone());
}
return clone;
}
}
จากนั้นคุณสามารถโคลนพจนานุกรมได้ง่ายๆโดยการเรียกClone
วิธีการ ของหลักสูตรการดำเนินงานนี้ต้องว่าประเภทค่าของการดำเนินการพจนานุกรมICloneable
แต่อย่างอื่นการใช้งานทั่วไปไม่จริงที่ทุกคน
มันใช้งานได้ดีสำหรับฉัน
// assuming this fills the List
List<Dictionary<string, string>> obj = this.getData();
List<Dictionary<string, string>> objCopy = new List<Dictionary<string, string>>(obj);
ดังที่ Tomer Wolberg อธิบายไว้ในความคิดเห็นสิ่งนี้ไม่ทำงานหากประเภทค่าเป็นคลาสที่ไม่แน่นอน
คุณสามารถใช้การทำให้เป็นอนุกรมได้เสมอ คุณสามารถทำให้วัตถุเป็นอันดับ ที่จะให้คุณคัดลอกพจนานุกรมและรายการทั้งหมดในนั้น ตอนนี้คุณสามารถสร้างสำเนาลึกของวัตถุใด ๆ ที่ทำเครื่องหมายเป็น [ต่อเนื่อง] โดยไม่ต้องเขียนโค้ดพิเศษใด ๆ
ต่อไปนี้เป็นสองวิธีที่จะใช้การทำให้เป็นอันดับแบบไบนารี หากคุณใช้วิธีการเหล่านี้คุณเพียงแค่โทร
object deepcopy = FromBinary(ToBinary(yourDictionary));
public Byte[] ToBinary()
{
MemoryStream ms = null;
Byte[] byteArray = null;
try
{
BinaryFormatter serializer = new BinaryFormatter();
ms = new MemoryStream();
serializer.Serialize(ms, this);
byteArray = ms.ToArray();
}
catch (Exception unexpected)
{
Trace.Fail(unexpected.Message);
throw;
}
finally
{
if (ms != null)
ms.Close();
}
return byteArray;
}
public object FromBinary(Byte[] buffer)
{
MemoryStream ms = null;
object deserializedObject = null;
try
{
BinaryFormatter serializer = new BinaryFormatter();
ms = new MemoryStream();
ms.Write(buffer, 0, buffer.Length);
ms.Position = 0;
deserializedObject = serializer.Deserialize(ms);
}
finally
{
if (ms != null)
ms.Close();
}
return deserializedObject;
}
วิธีที่ดีที่สุดสำหรับฉันคือ:
Dictionary<int, int> copy= new Dictionary<int, int>(yourListOrDictionary);
วิธีการทำให้เป็นอนุกรมของไบนารีทำงานได้ดี แต่ในการทดสอบของฉันมันแสดงให้เห็นว่าช้ากว่าการใช้โคลนที่ไม่ใช่การทำให้เป็นอนุกรม ทดสอบแล้วDictionary<string , List<double>>
ToBinary()
Serialize()
this
yourDictionary
FromBinary()
นั่นคือสิ่งที่ช่วยฉันได้เมื่อฉันพยายามคัดลอกพจนานุกรม <string, string>
Dictionary<string, string> dict2 = new Dictionary<string, string>(dict);
โชคดี
ลองใช้วิธีนี้หากคีย์ / ค่านั้นเป็น ICloneable:
public static Dictionary<K,V> CloneDictionary<K,V>(Dictionary<K,V> dict) where K : ICloneable where V : ICloneable
{
Dictionary<K, V> newDict = null;
if (dict != null)
{
// If the key and value are value types, just use copy constructor.
if (((typeof(K).IsValueType || typeof(K) == typeof(string)) &&
(typeof(V).IsValueType) || typeof(V) == typeof(string)))
{
newDict = new Dictionary<K, V>(dict);
}
else // prepare to clone key or value or both
{
newDict = new Dictionary<K, V>();
foreach (KeyValuePair<K, V> kvp in dict)
{
K key;
if (typeof(K).IsValueType || typeof(K) == typeof(string))
{
key = kvp.Key;
}
else
{
key = (K)kvp.Key.Clone();
}
V value;
if (typeof(V).IsValueType || typeof(V) == typeof(string))
{
value = kvp.Value;
}
else
{
value = (V)kvp.Value.Clone();
}
newDict[key] = value;
}
}
}
return newDict;
}
ตอบกลับโพสต์เก่า แต่ฉันพบว่ามีประโยชน์ในการห่อดังนี้
using System;
using System.Collections.Generic;
public class DeepCopy
{
public static Dictionary<T1, T2> CloneKeys<T1, T2>(Dictionary<T1, T2> dict)
where T1 : ICloneable
{
if (dict == null)
return null;
Dictionary<T1, T2> ret = new Dictionary<T1, T2>();
foreach (var e in dict)
ret[(T1)e.Key.Clone()] = e.Value;
return ret;
}
public static Dictionary<T1, T2> CloneValues<T1, T2>(Dictionary<T1, T2> dict)
where T2 : ICloneable
{
if (dict == null)
return null;
Dictionary<T1, T2> ret = new Dictionary<T1, T2>();
foreach (var e in dict)
ret[e.Key] = (T2)(e.Value.Clone());
return ret;
}
public static Dictionary<T1, T2> Clone<T1, T2>(Dictionary<T1, T2> dict)
where T1 : ICloneable
where T2 : ICloneable
{
if (dict == null)
return null;
Dictionary<T1, T2> ret = new Dictionary<T1, T2>();
foreach (var e in dict)
ret[(T1)e.Key.Clone()] = (T2)(e.Value.Clone());
return ret;
}
}
entry.Value
ค่าอาจจะยังอีก [ย่อย] คอลเลกชัน