답변:
좋아, .NET 2.0 답변 :
값을 복제 할 필요가 없으면 생성자 오버로드를 기존 IDictionary를 사용하는 Dictionary에 사용할 수 있습니다. 비교자를 기존 사전의 비교 자로 지정할 수도 있습니다.
당신이 경우 않는 값을 복제 할 필요가, 당신은 이런 식으로 뭔가를 사용할 수 있습니다 :
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 버전은 무엇입니까? .NET 3.5를 사용하는 경우 키와 요소 선택기를 모두 지정하는 ToDictionary에 대한 LINQ 호출이 가장 쉬운 방법이라고 생각합니다.
예를 들어, 값이 얕은 복제본이 아니라면
var newDictionary = oldDictionary.ToDictionary(entry => entry.Key,
entry => entry.Value);
ICloneable을 구현하도록 T를 이미 제한 한 경우 :
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가 설명했듯이 값 유형이 변경 가능한 클래스 인 경우 작동하지 않습니다.
항상 직렬화를 사용할 수 있습니다. 객체를 직렬화 한 다음 역 직렬화 할 수 있습니다. 그러면 사전과 그 안의 모든 항목에 대한 깊은 사본이 제공됩니다. 이제 특수 코드를 작성하지 않고 [Serializable]로 표시된 모든 객체의 딥 카피를 만들 수 있습니다.
이진 직렬화를 사용하는 두 가지 방법이 있습니다. 이 방법을 사용하면 간단히 전화하십시오.
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 <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
값은 또 다른 [sub] 컬렉션 일 수 있습니다.