The .NET Dictionary<TKey, TValue> object allows assignment of key/values like so:
Dictionary<string, string> dict = new Dictionary<string, string>();
dict["1"] = "foo";
dict["2"] = "bar";
but I cannot use a Dictionary like so:
Dictionary<string, string> dict = new Dictionary<string, string>();
dict["F1"]["F2"]["F3"] = "foo";
dict["2"]["X"] = "bar";
Is there a collection in .NET which allows me to nest [], or would I have to create my own?
If I have to create my own, how would I do this?
EDIT:
It would also be useful if I could have implementations which expect unique keys, like so:
dict["F1"]["F2"]["F3"] = "foo";
dict["F1"]["F2"]["F3"] = "bar"; //result is "bar" because "foo" was overridden
and an implementation where a key can be used more than once
dict["F1"]["F2"]["F3"] = "foo";
dict["F1"]["F2"]["F3"] = "bar"; //result can be "foo" and "bar"
Is this possible?
EDIT (as per Jon Skeet's question):
I want to use the structure like so (as a very rough example):
json["data"]["request"]["name"] = "username";
json["data"]["request"]["pass"] = "password";
resolves to
{ data: { request: { name: "username", pass: "password" } } }
and equally there would be an equivalent for XML etc.
Having a requirement for arbitrarily long nesting, I have come up with the following solution, which as far as I can see, doesn't break, according to my test:
public class NestedDictionary<K, V> : Dictionary<K, NestedDictionary<K, V>>
{
public V Value { set; get; }
public new NestedDictionary<K, V> this[K key]
{
set { base[key] = value; }
get
{
if (!base.Keys.Contains<K>(key))
{
base[key] = new NestedDictionary<K, V>();
}
return base[key];
}
}
}
TEST:
NestedDictionary<string, string> dict = new NestedDictionary<string, string>();
dict["one"].Value = "Nest level 1";
dict["one"]["two"]["three"].Value = "Nest level 3";
dict["FieldA"]["FieldB"].Value = "Hello World";
Console.WriteLine(dict["one"].Value);
Console.WriteLine(dict["one"]["two"]["three"].Value);
Console.WriteLine(dict["FieldA"]["FieldB"].Value);
You can do this using the standard Dictionary, you just have to declare the nesting:
Dictionary<string, Dictionary<string, string>> dict = ...
string test = dict["first"]["second"]
Dictionary<string, Dictionary<string, Dictionary<string, string>>> dict = ...
string test = dict["first"]["second"]["third"]
etc
The original Dictionary COM object which was created to work with vb6 would respond to an attempt to access a non-existent item by creating a new item of type Dictionary with the corresponding name. This approach allows something to be stored to MyDict["Foo"]["Bar"] without having to first create MyDict["Foo"]. The problem with this approach is that while one would want to add "Foo" to MyDict when performing a write to MyDict["Foo"]["Bar"], one would rather not create such an item if one was attempting to e.g. evaluate MyDict["Foo"]["Bar"].ValueOrDefault(someDefaultValue).
I've used such collections, since they can be handy for modeling certain things (conceptually they're a lot like XML documents). One workable approach is to declare that dictionaries which contain nothing but other dictionaries are considered semantically as non-entities which may be removed at any opportunity. When implicitly adding a subcollection, set a flag in the item to which it's added it indicating that it should be checked for items that may be deleted (or keep a counter of how many such items may exist). Then with some reasonable frequency, scan through the dictionaries and remove such "dead" items.
An alternative approach is to have the indexer from the dictionary not return an actual item, but instead return an "ephemeral indexer" type, which keeps a reference to the parent object and has internal methods GetNestedForReading, SetNestedForReading, GetValue, and SetValue, which chain back to it. Then a statement Foo["Bar"]["Boz"] = "George"; will end up effectively performing Foo.SetNestedForReading("Bar").SetValue("Boz", "George"); while z = Foo["Bar"]["Boz"]; will effectively perform Foo.GetNestedForReading("Bar").GetValue("Boz");. Calling SetNestedForReading method with a non-existent key will create and return a new nested item; the GetNestedForReading method will an immutable "empty" item. Using this approach will thus avoid creating empty items.
Although the latter approach is more complicated than the former, it has another advantage. It's possible to have each node to individually hold its collection as either a shared deeply-immutable dictionary or an unshared mutable one; if a GetNestedForWriting call sees that the nested object is immutable, it can construct a new shallowly-mutable object holding the same items. If one defines the cloning method for a mutable node as creating a new immutable node with (immutable) clones of all subnodes, and the cloning method of an immutable node as returning itself, cloning trees that are mostly immutable becomes very cheap. If one had a newly-cloned (thus immutable) four-level tree with sixteen items on each level (65,536 leaf nodes total) and all the nodes were shared-immutable, updating a leaf node would only require replacing one leaf and four other nodes with mutable ones. Cloning the tree again would only require creating new immutable objects for the nodes which had been replaced with mutable ones (e.g. copying five things). Although one would have the convenience of a fully-mutable tree, one would have the efficiency advantages of an immutable one.
The biggest "problem" I see with this approach is that to avoid some weird behaviors one must require the use of syntax like MyDict["Foo"]["Bar"].Value = "George". If implicit conversion operators were used to avoid that requirement, someone would expect a statement like var st = MyThing["Foo"]["Bar"]; to define st as a string snapshot of whatever MyThing["Foo"]["Bar"] holds at that moment; instead it would define it as something that will index MyThing["Foo"]["Bar"]. If one had to use .Value to read or write strings from such a type, the fact that the variable wasn't a string would be apparent. If one used implicit operators to allow such assignments, the behavior would be odd. It's too bad there's no way a function can specify "do not allow this return value to be used for type inference".
Incidentally, it's possible to have the indexer type be a class or a generic struct. If it's a class, an access to foo["Bar"]["boz"]["baz"]... nested N deep would likely require the creation of N temporary heap objects. If it's a generic struct, it would entail the creation of N structs, but the more-deeply-nested structs would get bigger. For reasonable levels of nesting, generic structs would probably be slightly more efficient, but classes would probably be easier to work with.
You have to decide on either supporting a fixed number of string keys to look up, or provide a more general key mechanism if the number of keys can vary. For the first case try the following:
Dictionary<string,Dictionary<string,string>> dict =
Dictionary<string,Dictionary<string,string>>();
dict["F1"]["F2"] = "foo";
Dictionary<string,Dictionary<string,Dictionary<string,string>>> dict2 =
Dictionary<string,Dictionary<string,string>>();
dict2["F1"]["F2"]["F3"] = "bar";
For the second case, you could do the following:
Dictionary<string[],string> dict = new Dictionary<string[],string>(new MyEqualityComparer());
dict[new string[] {"F1","F2"}] = "foo";
dict[new string[] {"F1","F2","F3"}] = "bar";
where the class MyEqualityComparer would be something like:
public class MyEqualityComparer : IEqualityComparer<string[]>
{
public int GetHashCode(string[]item)
{
int hashcode = 0;
foreach (string s in item)
{
hashcode |= s.GetHashCode();
}
return hashcode;
}
public bool Equals(string [] a, string [] b)
{
if (a.Length != b.Length)
return false;
for (int i = 0; i < a.Length; ++i)
{
if (a[i] != b[i])
return false;
}
return true;
}
Use a Dictionary as TValue:
var dict2 = new Dictionary<string, Dictionary<string, string>>();
var dict3 = new Dictionary<string, Dictionary<string, Dictionary<string, string>>>();
for example:
var dict =
new Dictionary<string, Dictionary<string, string>>
{
{
"F1", new Dictionary<string, string>
{
{"F2", "foo"}
}
}
};
dict["F1"]["F2"] = "bar";
I think, your case is good place to use DynamicObject. I'll create an example for json using Dictionary<string, object> internally.
Same idea can be used for xml also.
string json = #"{""Name"":""Joe"",
""Age"":30,
""Address"":{ ""City"":""NY"" }}";
dynamic dynObj = new DynamicJson(json);
Console.WriteLine(dynObj.Name);
Console.WriteLine(dynObj.Age);
Console.WriteLine(dynObj.Address.City);
--
public class DynamicJson : DynamicObject
{
Dictionary<string, object> _Dict;
public DynamicJson(string json)
{
_Dict = (Dictionary<string, object>)new JavaScriptSerializer().DeserializeObject(json);
}
DynamicJson(Dictionary<string, object> dict)
{
_Dict = dict;
}
public override bool TryGetMember(GetMemberBinder binder, out object result)
{
result = null;
object obj;
if (!_Dict.TryGetValue(binder.Name, out obj)) return false;
if (obj is Dictionary<string, object>)
{
result = new DynamicJson((Dictionary<string, object>)obj);
}else
{
result = obj;
}
return true;
}
}
Related
I have a dictionary:
Dictionary<String, List<Foo>> test = new Dictionary<String, List<Foo>>();
I then populate this dictionary hence why I need the list so I can call Add(). My problem is the function needs to return:
Dictionary<String, IEnumerable<Foo>>
Is there any easy way to do this without doing the obvious and looping through my original dictionary and doing it manually?
return dictionary.ToDictionary(x => x.Key,x => x.Value.AsEnumerable())
It's more efficient and easier to use the List<Foo> to add things but add it to a Dictionary<String, IEnumerable<Foo>>. That's no problem since List<Foo> implements IEnumerable<Foo>, it's not even necessary to cast.
So something like this(pseudo code):
var test = new Dictionary<String, IEnumerable<Foo>>();
foreach(var x in something)
{
var list = new List<Foo>();
foreach(var y in x.SomeCollection)
list.Add(y.SomeProperty);
test.Add(x.KeyProperty, list); // works since List<T> is also an IEnumerable<T>
}
I tried this route as well, converting Dictionary<string, List<Foo>> to a ReadOnlyDictionary<string, IEnumerable<Foo>>. While I was trying to convert to a read-only dictionary, the whole purpose of converting a List to IEnumerable is to make a read only collection. The problem with the OP's approach is:
Dictionary<string, List<string>> errors = new Dictionary<string, List<string>>();
errors["foo"] = new List<string>() { "You can't do this" };
Dictionary<string, IEnumerable<string>> readOnlyErrors = // convert errors...
readOnlyErrors["foo"] = new List<string>() { "I'm not actually read-only!" };
The appearance of IEnumerable<Foo> makes you think this is read only and safe, when in fact it is not. After reading the question LINQ Convert Dictionary to Lookup a Lookup object is more appropriate, because it allows you to:
Associate one key with multiple values
You cannot overwrite a key with a new value
// This results in a compiler error
lookUp["foo"] = new List<Foo>() { ... };
The "multiple values" are already defined as IEnumerable<T>
You can still use the same outer and inner loop algorithm to extract individual values:
ILookup<string, string> lookup = // Convert to lookup
foreach (IGrouping<string, string> grouping in lookup)
{
Console.WriteLine(grouping.Key + ":");
foreach (string item in grouping)
{
Console.WriteLine(" item: " + item);
}
}
Convert Dictionary<string, List<Foo>> to ILookup<string, Foo>
It's a quick two-liner:
Dictionary<string, List<Foo>> foos = // Create and populate 'foos'
ILookup<string, Foo> lookup = foos.SelectMany(item => item.Value, Tuple.Create)
.ToLookup(p => p.Item1.Key, p => p.Item2);
Now you can use the same two-step loop as you would have with a Dictionary<string, IEnumerable<Foo>>:
foreach (IGrouping<string, Foo> grouping in lookup)
{
string key = grouping.Key;
foreach (Foo foo in grouping)
{
// Do stuff with key and foo
}
}
Source: LINQ Convert Dictionary to Lookup
Converting to another Dictionary with an IEnumerable value is like trying to stuff a square peg into a round hole. The more appropriate, and safe way (from an object-oriented standpoint) is to convert your read/write Dictionary to a Lookup. This gives you the true intended safety of an object that is read-only (except for the Foo items, which might not be immutable).
I would go so far as to say that most times when a ReadOnlyDictionary is used, you could use ILookup and get the same functionality.
I have an application that use managed dlls. One of those dlls return a generic dictionary:
Dictionary<string, int> MyDictionary;
The dictionary contains keys with upper and lower case.
On another side I am getting a list of potential keys (string) however I cannot guarantee the case. I am trying to get the value in the dictionary using the keys. But of course the following will fail since I have a case mismatch:
bool Success = MyDictionary.TryGetValue( MyIndex, out TheValue );
I was hoping the TryGetValue would have an ignore case flag like mentioned in the MSDN doc, but it seems this is not valid for generic dictionaries.
Is there a way to get the value of that dictionary ignoring the key case?
Is there a better workaround than creating a new copy of the dictionary with the proper StringComparer.OrdinalIgnoreCase parameter?
There's no way to specify a StringComparer at the point where you try to get a value. If you think about it, "foo".GetHashCode() and "FOO".GetHashCode() are totally different so there's no reasonable way you could implement a case-insensitive get on a case-sensitive hash map.
You can, however, create a case-insensitive dictionary in the first place using:-
var comparer = StringComparer.OrdinalIgnoreCase;
var caseInsensitiveDictionary = new Dictionary<string, int>(comparer);
Or create a new case-insensitive dictionary with the contents of an existing case-sensitive dictionary (if you're sure there are no case collisions):-
var oldDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
var newDictionary = new Dictionary<string, int>(oldDictionary, comparer);
This new dictionary then uses the GetHashCode() implementation on StringComparer.OrdinalIgnoreCase so comparer.GetHashCode("foo") and comparer.GetHashcode("FOO") give you the same value.
Alternately, if there are only a few elements in the dictionary, and/or you only need to lookup once or twice, you can treat the original dictionary as an IEnumerable<KeyValuePair<TKey, TValue>> and just iterate over it:-
var myKey = ...;
var myDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
var value = myDictionary.FirstOrDefault(x => String.Equals(x.Key, myKey, comparer)).Value;
Or if you prefer, without the LINQ:-
var myKey = ...;
var myDictionary = ...;
var comparer = StringComparer.OrdinalIgnoreCase;
int? value;
foreach (var element in myDictionary)
{
if (String.Equals(element.Key, myKey, comparer))
{
value = element.Value;
break;
}
}
This saves you the cost of creating a new data structure, but in return the cost of a lookup is O(n) instead of O(1).
For you LINQers out there that never use a regular dictionary constructor
myCollection.ToDictionary(x => x.PartNumber, x => x.PartDescription, StringComparer.OrdinalIgnoreCase)
There is much simpler way:
using System;
using System.Collections.Generic;
....
var caseInsensitiveDictionary = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
Its not very elegant but in case you cant change the creation of dictionary, and all you need is a dirty hack, how about this:
var item = MyDictionary.Where(x => x.Key.ToLower() == MyIndex.ToLower()).FirstOrDefault();
if (item != null)
{
TheValue = item.Value;
}
I currently have a WebSocket between JavaScript and a server programmed in C#. In JavaScript, I can pass data easily using an associative array:
var data = {'test': 'val',
'test2': 'val2'};
To represent this data object on the server side, I use a Dictionary<string, string>, but this is more 'typing-expensive' than in JavaScript:
Dictionary<string, string> data = new Dictionary<string,string>();
data.Add("test", "val");
data.Add("test2", "val2");
Is there some kind of literal notation for associative arrays / Dictionarys in C#?
You use the collection initializer syntax, but you still need to make a new Dictionary<string, string> object first as the shortcut syntax is translated to a bunch of Add() calls (like your code):
var data = new Dictionary<string, string>
{
{ "test", "val" },
{ "test2", "val2" }
};
In C# 6, you now have the option of using a more intuitive syntax with Dictionary as well as any other type that supports indexers. The above statement can be rewritten as:
var data = new Dictionary<string, string>
{
["test"] = "val",
["test2"] = "val2"
};
Unlike collection initializers, this invokes the indexer setter under the hood, rather than an appropriate Add() method.
While, the dictionary initializer answer is totally correct, there is another approach to this that I would point out (but I might not recommend it). If your goal is to provide terse API usage, you could use anonymous objects.
var data = new { test1 = "val", test2 = "val2"};
The "data" variable is then of an "unspeakable" anonymous type, so you could only pass this around as System.Object. You could then write code that can transform an anonymous object into a dictionary. Such code would rely on reflection, which would potentially be slow. However, you could use System.Reflection.Emit, or System.Linq.Expressions to compile and cache a delegate that would make subsequent calls much faster.
Asp.net MVC APIs use this technique in a number of places that I've seen. A lot of the Html Helpers have overloads that accept either an object or a dictionary. I assume the goal of their API design is the same as what you are after; terse syntax at the method call.
Use Dictionary Literals (C#9 proposal) [rejected] or the new syntax (beginning with C#9)
C#9 introduces a simpler syntax to create initialized Dictionary<TKey,TValue> objects without having to specify either the Dictionary type name or the type parameters. The type parameters for the dictionary are inferred using the existing rules used for array type inference.
// C# 1..8
var x = new Dictionary <string,int> () { { "foo", 4 }, { "bar", 5 }};
// C# 9
var x = ["foo":4, "bar": 5];
This synthax makes the work with dictionaries in C# simpler and removing the redundant code.
You can follow the issue on GitHub (and here is the milestone for C#9).
Edit: This proposal is currently rejected:
[...] We think there are a number of interesting use cases around initializing data, particularly for things like immutable dictionaries. We don't find the existing syntax for initializing a dictionary that onerous, nor do we see it as a frequent pattern in code that would benefit much from a language feature. We thing that the general area of initializing data should be looked at again after we do records and withers. [...]
current milestone:
Note that beginning with C# 9.0, constructor invocation expressions are target-typed. That is, if a target type of an expression is known, you can omit a type name, as the following example shows:
Dictionary<int, List<int>> lookup = new()
{
[1] = new() {1, 2, 3},
[2] = new() {5, 8, 3},
[5] = new() {1, 0, 4}
};
As the preceding example shows, you always use parentheses in a target-typed new expression.
If a target type of a new expression is unknown (for example, when you use the var keyword), you must specify a type name.
MSDN
Using DynamicObject, it is not that difficult to create a simpler dictionary initializer.
Imagine you want to call the following method
void PrintDict(IDictionary<string, object> dict) {
foreach(var kv in dict) {
Console.WriteLine (" -> " + kv.Key + " = " + kv.Value);
}
}
using a literal syntax like
var dict = Dict (Hello: "World", IAm: "a dictionary");
PrintDict (dict);
This can be accomplished by creating a dynamic object like this
dynamic Dict {
get {
return new DynamicDictFactory ();
}
}
private class DynamicDictFactory : DynamicObject
{
public override bool TryInvoke (InvokeBinder binder, object[] args, out object result)
{
var res = new Dictionary<string, object> ();
var names = binder.CallInfo.ArgumentNames;
for (var i = 0; i < args.Length; i++) {
var argName = names [i];
if(string.IsNullOrEmpty(argName)) throw new ArgumentException();
res [argName] = args [i];
}
result = res;
return true;
}
}
This test fails:
using Microsoft.VisualStudio.TestTools.UnitTesting;
[TestMethod()]
public void dictEqualTest() {
IDictionary<string, int> dict = new Dictionary<string, int>();
IDictionary<string, int> dictClone = new Dictionary<string, int>();
for (int x = 0; x < 3; x++) {
dict[x.ToString()] = x;
dictClone[x.ToString()] = x;
}
Assert.AreEqual(dict, dictClone); // fails here
Assert.IsTrue(dict.Equals(dictClone)); // and here, if the first is commented out
Assert.AreSame(dict, dictClone); // also fails
}
Am I misunderstanding something about how a Dictionary works?
I'm looking for the Java equivalent of .equals(), not trying to check referential equality.
Dictionary class does not override Object.Equals method as seen from MSDN doco:
http://msdn.microsoft.com/en-us/library/bsc2ak47.aspx
Determines whether the specified
Object is equal to the current Object.
Seeing that you are doing unit testing, your Assert class should provide a test method for testing if two collections are the same.
Microsoft Unit testing framework provides CollectionAssert class for the purpose of comparing collections:
http://msdn.microsoft.com/en-us/library/microsoft.visualstudio.testtools.unittesting.collectionassert_members%28VS.80%29.aspx
EDIT Dictionary implements ICollection interface, can you see if that just works? You might need to use this overload to compare two dictionary entries.
EDIT Hmm IDictionary does not implement ICollection, which is a bit of a pain. This however works (albeit a hack):
IDictionary<string, int> dict = new Dictionary<string, int>();
IDictionary<string, int> dictClone = new Dictionary<string, int>();
for(int x = 0; x < 3; x++) {
dict[x.ToString()] = x;
dictClone[x.ToString()] = x;
}
CollectionAssert.AreEqual((System.Collections.ICollection)dict, (System.Collections.ICollection)dictClone);
THe above approach will work for instances of Dictionary, however if you are testing a method that returns IDictionary it might fail if the implmentation changes. My advice is to change the code to use Dictionary instead of IDictionary (since IDictionary is not readonly, so you are not hiding all that much by using that instead of concreate Dictionary).
If you are specifically interested in how you can fix this from unit testing perspective:
Try this
CollectionAssert.AreEquivalent(dict.ToList(), dictClone.ToList());
Explanation
There are extension methods on IDictionary - such as .ToList() - available in .Net 3.5 and up, which will convert the dictionary into a collection of KeyValuePair that can be easily compared with CollectionAssert.AreEquivalent.
They'll even give reasonably helpful error messages! Example usage:
IDictionary<string, string> d1 = new Dictionary<string, string> {
{ "a", "1"}, {"b", "2"}, {"c", "3"}};
IDictionary<string, string> d2 = new Dictionary<string, string> {
{"b", "2"}, { "a", "1"}, {"c", "3"}}; // same key-values, different order
IDictionary<string, string> d3 = new Dictionary<string, string> {
{ "a", "1"}, {"d", "2"}, {"c", "3"}}; // key of the second element differs from d1
IDictionary<string, string> d4 = new Dictionary<string, string> {
{ "a", "1"}, {"b", "4"}, {"c", "3"}}; // value of the second element differs from d1
CollectionAssert.AreEquivalent(d1.ToList(), d2.ToList());
//CollectionAssert.AreEquivalent(d1.ToList(), d3.ToList()); // fails!
//CollectionAssert.AreEquivalent(d1.ToList(), d4.ToList()); // fails!
// if uncommented, the 2 tests above fail with error:
// CollectionAssert.AreEquivalent failed. The expected collection contains 1
// occurrence(s) of <[b, 2]>. The actual collection contains 0 occurrence(s).
The problem is with this line of code:
Assert.AreEqual(dict, dictClone)
You are comparing object references, which aren't equal.
I have used an extension method that checks two sequences for equal items
public static bool CheckForEquality<T>(this IEnumerable<T> source, IEnumerable<T> destination)
{
if (source.Count() != destination.Count())
{
return false;
}
var dictionary = new Dictionary<T, int>();
foreach (var value in source)
{
if (!dictionary.ContainsKey(value))
{
dictionary[value] = 1;
}
else
{
dictionary[value]++;
}
}
foreach (var member in destination)
{
if (!dictionary.ContainsKey(member))
{
return false;
}
dictionary[member]--;
}
foreach (var kvp in dictionary)
{
if (kvp.Value != 0)
{
return false;
}
}
return true;
}
You are completely not understanding how reference types work.
Dictionary does not override object.Equals(). Thus, it uses reference equality - basically, if both references are pointing to the same instance, they're equal, otherwise they aren't.
The NUnit class CollectionAssert has an AreEquivalent method which accepts IEnumerable as parameters, so in that case it's as simple as
CollectionAssert.AreEquivalent(dict, dictClone);
because Dictionary implements IEnumerable.
There doesn't seem to be a dictionary.AddRange() method. Does anyone know a better way to copy the items to another dictionary without using a foreach loop.
I'm using the System.Collections.Generic.Dictionary. This is for .NET 2.0.
There's the Dictionary constructor that takes another Dictionary.
You'll have to cast it IDictionary, but there is an Add() overload that takes KeyValuePair<TKey, TValue>. You're still using foreach, though.
There's nothing wrong with a for/foreach loop. That's all a hypothetical AddRange method would do anyway.
The only extra concern I'd have is with memory allocation behaviour, because adding a large number of entries could cause multiple reallocations and re-hashes. There's no way to increase the capacity of an existing Dictionary by a given amount. You might be better off allocating a new Dictionary with sufficient capacity for both current ones, but you'd still need a loop to load at least one of them.
var Animal = new Dictionary<string, string>();
one can pass existing animal Dictionary to the constructor.
Dictionary<string, string> NewAnimals = new Dictionary<string, string>(Animal);
For fun, I created this extension method to dictionary. This should do a deep copy wherever possible.
public static Dictionary<TKey, TValue> DeepCopy<TKey,TValue>(this Dictionary<TKey, TValue> dictionary)
{
Dictionary<TKey, TValue> d2 = new Dictionary<TKey, TValue>();
bool keyIsCloneable = default(TKey) is ICloneable;
bool valueIsCloneable = default(TValue) is ICloneable;
foreach (KeyValuePair<TKey, TValue> kvp in dictionary)
{
TKey key = default(TKey);
TValue value = default(TValue);
if (keyIsCloneable)
{
key = (TKey)((ICloneable)(kvp.Key)).Clone();
}
else
{
key = kvp.Key;
}
if (valueIsCloneable)
{
value = (TValue)((ICloneable)(kvp.Value)).Clone();
}
else
{
value = kvp.Value;
}
d2.Add(key, value);
}
return d2;
}
If you're dealing with two existing objects, you might get some mileage with the CopyTo method: http://msdn.microsoft.com/en-us/library/cc645053.aspx
Use the Add method of the other collection (receiver) to absorb them.
I don't understand, why not using the Dictionary( Dictionary ) (as suggested by ageektrapped ).
Do you want to perform a Shallow Copy or a Deep Copy? (that is, both Dictionaries pointing to the same references or new copies of every object inside the new dictionary?)
If you want to create a new Dictionary pointing to new objects, I think that the only way is through a foreach.
For a primitive type dictionary:
public void runIntDictionary()
{
Dictionary<int, int> myIntegerDict = new Dictionary<int, int>() { { 0, 0 }, { 1, 1 }, { 2, 2 } };
Dictionary<int, int> cloneIntegerDict = new Dictionary<int, int>();
cloneIntegerDict = myIntegerDict.Select(x => x.Key).ToList().ToDictionary<int, int>(x => x, y => myIntegerDict[y]);
}
or with an Object that implement ICloneable:
public void runObjectDictionary()
{
Dictionary<int, number> myDict = new Dictionary<int, number>() { { 3, new number(3) }, { 4, new number(4) }, { 5, new number(5) } };
Dictionary<int, number> cloneDict = new Dictionary<int, number>();
cloneDict = myDict.Select(x => x.Key).ToList().ToDictionary<int, number>(x => x, y => myDict[y].Clone());
}
public class number : ICloneable
{
public number()
{
}
public number(int newNumber)
{
nr = newnumber;
}
public int nr;
public object Clone()
{
return new number() { nr = nr };
}
public override string ToString()
{
return nr.ToString();
}
}
The reason AddRange is not implemented on Dictionary is due to the way in which a hashtable (i.e. Dictionary) stores its entries: They're not contiguous in memory as we see in an array or a List, instead they're fragmented across multiple hash buckets, so you cannot block-copy the whole range into a List or you'll get a bunch of empty entries which the Dictionary usually hides from you, the user, through its interface. AddRange assumes a single contiguous range of valid data and can therefore use a fast copy implementation e.g.Array.Copy (like C's memcpy).
Due to this fragmentation, we are left no choice but to iterate through the Dictionary's entries manually in order to extract valid keys and values into a single contiguous List or array. This can be confirmed in Microsoft's reference implementation, where CopyTo is implemented using for.