我有一个通用字典dictionary <string, T>,我想基本上使克隆()..任何建议。


当前回答

对于。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,但除此之外,泛型实现根本不实用。

其他回答

(注意:虽然克隆版本可能很有用,但对于简单的浅复制,我在另一篇文章中提到的构造函数是更好的选择。)

你希望拷贝的深度是多少,你使用的是什么版本的。net ?如果你使用的是。net 3.5,我认为对ToDictionary的LINQ调用,同时指定键和元素选择器将是最简单的方法。

例如,如果你不介意这个值是一个浅克隆:

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, Dictionary<string, dynamic>> buildInfoDict =
    new Dictionary<string, Dictionary<string, dynamic>>()
    {
        {"tag",new Dictionary<string,dynamic>(){
                 { "attrName", "tag"  },
                 { "isCss", "False"  },
               { "turnedOn","True" },
                 { "tag",null }
            } },
        {"id",new Dictionary<string,dynamic>(){
                 { "attrName", "id"  },
                 { "isCss", "False"  },
               { "turnedOn","True" },
                 { "id",null }
            } },
                {"width",new Dictionary<string,dynamic>(){
                 { "attrName", "width"  },
                 { "isCss", "True"  },
               { "turnedOn","True" },
                 { "width","20%" }
            } },
                {"height",new Dictionary<string,dynamic>(){
                 { "attrName", "height"  },
                 { "isCss", "True"  },
               { "turnedOn","True" },
                 { "height","20%" }
            } },
                {"text",new Dictionary<string,dynamic>(){
                 { "attrName", null  },
                 { "isCss", "False"  },
               { "turnedOn","True" },
                 { "text","" }
            } },
                {"href",new Dictionary<string,dynamic>(){
                 { "attrName", null  },
                 { "isCss", "False"  },
                 { "flags", "removeAttrIfTurnedOff"  },
               { "turnedOn","True" },
                 { "href","about:blank" }
            } }
    };

var cln=clone(buildInfoDict);

public static dynamic clone(dynamic obj)
{
    dynamic cloneObj = null;
    if (IsAssignableFrom(obj, typeof(IDictionary)))
    {
        cloneObj = Activator.CreateInstance(obj.GetType());
        foreach (var key in obj.Keys)
        {
            cloneObj[key] = clone(obj[key]);
        }

    }
    else if (IsNumber(obj) || obj.GetType() == typeof(string))
    {
        cloneObj = obj;
    }
    else
    {
        Debugger.Break();
    }
    return cloneObj;
}


public static bool IsAssignableFrom(this object obj, Type ObjType = null, Type ListType = null, bool HandleBaseTypes = false)
{
    if (ObjType == null)
    {
        ObjType = obj.GetType();
    }

    bool Res;

    do
    {
        Res = (ObjType.IsGenericType && ObjType.GetGenericTypeDefinition().IsAssignableFrom(ListType)) ||
            (ListType == null && ObjType.IsAssignableFrom(obj.GetType()));
        ObjType = ObjType.BaseType;
    } while ((!Res && ObjType != null) && HandleBaseTypes && ObjType != typeof(object));

    return Res;
}

public static bool IsNumber(this object value)
{
    return value is sbyte
            || value is byte
            || value is short
            || value is ushort
            || value is int
            || value is uint
            || value is long
            || value is ulong
            || value is float
            || value is double
            || value is decimal;
}

如果键/值是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;
    }

我将计算T是否为值或引用类型。如果T是值类型,我将使用Dictionary的构造函数,如果T是引用类型,我将确保T继承自ICloneable。

它会给

    private static IDictionary<string, T> Copy<T>(this IDictionary<string, T> dict)
         where T : ICloneable
    {
        if (typeof(T).IsValueType)
        {
            return new Dictionary<string, T>(dict);
        }
        else
        {
            var copy = new Dictionary<string, T>();
            foreach (var pair in dict)
            {
                copy[pair.Key] = pair.Value;
            }
            return copy;
        }
    }

这帮助了我,当我试图深度复制Dictionary < string, string >

Dictionary<string, string> dict2 = new Dictionary<string, string>(dict);

祝你好运