I am trying to create a recursive method that makes a deep copy of a dictionary to any length by checking if the hash value is another dictionary and then copy it again before hashing it.
I have tried this and the compiler rejects the line in Blockquote, who can find the error?
private Dictionary<TKey, TValue> NestedCopy<TKey, TValue>(Dictionary<TKey,
TValue> nestedDict)
{
var retDict = new Dictionary<TKey, TValue>();
foreach (var dict in nestedDict)
{
if (dict.Value is Dictionary<Object, Object>)
{
retDict[dict.Key] = NestedCopy(dict.Value asDictionary<object, object>);
}
}
return retDict;
}
retDict[dict.Key] = NestedCopy(dict.Value asDictionary);
This is the error line,
It says it cannot implicitly convert from Dictionary to TValue
Dictionary<string, Dictionary<string, int>> dict;
var newDict = NestedCopy(newDict);
//I expect newDict to be a copy of dict
答案 0 :(得分:2)
编译器无法静态推断递归调用。所以,你需要反思或者至少让编译器使用dynamic
关键字为你做反射:
private Dictionary<TKey, TValue> NestedCopy<TKey, TValue>(
Dictionary<TKey, TValue> nestedDict)
{
var retDict = new Dictionary<TKey, TValue>();
foreach (var dict in nestedDict)
{
if (typeof(TValue).IsGenericType && typeof(TValue).GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
retDict[dict.Key] = (TValue)NestedCopy((dynamic)dict.Value);
}
else
{
retDict[dict.Key] = dict.Value;
}
}
return retDict;
}
使用手工制作反射的更明确的代码可能如下所示:
private static Dictionary<TKey, TValue> NestedCopy<TKey, TValue>(
Dictionary<TKey, TValue> nestedDict)
{
var reflectionMethod = typeof(Program).GetMethod("NestedCopy", System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Static);
var retDict = new Dictionary<TKey, TValue>();
foreach (var dict in nestedDict)
{
if (typeof(TValue).IsGenericType && typeof(TValue).GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
var methodToCall = reflectionMethod.MakeGenericMethod(typeof(TValue).GetGenericArguments());
retDict[dict.Key] = (TValue)methodToCall.Invoke(null, new object[] { dict.Value });
}
else
{
retDict[dict.Key] = dict.Value;
}
}
return retDict;
}
请注意,这假设属于Program
类的方法,因为它不使用任何上下文,所以我将其设置为静态。
由于if-else
的决定并不取决于dict.Value
,而只取决于整个方法中保持不变的TValue
,因此您也可以将条件移出循环:
private static Dictionary<TKey, TValue> NestedCopy<TKey, TValue>(
Dictionary<TKey, TValue> nestedDict)
{
var retDict = new Dictionary<TKey, TValue>();
Func<TValue, TValue> clone;
if (typeof(TValue).IsGenericType && typeof(TValue).GetGenericTypeDefinition() == typeof(Dictionary<,>))
{
clone = v => NestedCopy((dynamic)v);
}
else
{
clone = v => v;
}
foreach (var dict in nestedDict)
{
retDict[dict.Key] = clone(dict.Value);
}
return retDict;
}
答案 1 :(得分:-1)
我认为你不需要递归它,它依赖于你如何实现TValue.Clone方法。
private Dictionary<TKey, TValue> CloneDictionary<TKey, TValue>(Dictionary<TKey, TValue> sourceDic)
where TValue : ICloneable
{
var ret = new Dictionary<TKey, TValue>(sourceDic.Count, sourceDic.Comparer);
foreach (KeyValuePair<TKey, TValue> entry in sourceDic)
{
ret.Add(entry.Key, (TValue)entry.Value.Clone());
}
return ret;
}