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.
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.
This may be an easy question, but I can't find the answer anywhere! As you'll be able to tell, I'm fairly new to coding.
I'm currently working on a project which uses a SortedList to store a string value as its key and a second SortedList as its value. The second SortedList has a series of numeric IDs (though stored as strings) as keys and another string as the value.
I've got no problem entering the values as above, but I'm having trouble accessing the second SortedList which is the value of the first.
I'm tying myself in knots trying to work it out and hope that someone may be able to point me in the right direction.
Sample (simlified) code below...
//New and empty SortedLists created
SortedList mySL1 = new SortedList();
SortedList mySL2 = new SortedList();
//Clicking button1 first ensures mySL2 is clear and then adds a couple of KVPs
//Then text entered into a textBox and mySL2 are added as a KVP to mySL1
private void button1_Click(object sender, EventArgs e)
{
mySL2.Clear();
mySL2.Add("w", "x");
mySL2.Add("y", "z");
mySL1.Add(textBox1.Text, mySL2);
}
//Clicking button2 outputs each of the keys of mySL1 to a listBox
private void button2_Click(object sender, EventArgs e)
{
for (int i = 0; i < mySL1.Count; i++)
{
listBox1.Items.Add(mySL1.GetKey(i));
}
}
private void button3_Click(object sender, EventArgs e)
{
for (int i = 0; i < mySL1.Count; i++)
{
//How do I access the KVPs of the mySL2 SortedLists which are the values of mySL1?
}
}
EDIT
I suspect that I've been unclear as to what I was asking and over complicated a fairly simple query by including for loops in my 'simple code'.
What I'm having problems with is the syntax of accessing a list within a list.
Suppose, as in the above example, I have a sorted list (mySL1) of which the value is a second sorted list (mySL2).
The syntax for accessing the key of mySL1 at index 5 is mySL1.GetKey(5)
What I'm trying to find out is the syntax for accessing a particular key or value in mySL2 of a particular index of mySL1, for example the key at index 6 of the mySL2 list which is (the value) at index 5 of mySL1.
As i may want to access specific keys or values from mySL2 a foreach loop won't be sufficient.
New Answer
Ok, I'm still not entirely sure what the original poster is looking for, but here is my
best guess with the information that I have so far:
private void button3_Click(object sender, EventArgs e)
{
for (int i = 0; i < listOfLists.Count; i++)
{
var list = (SortedList) listOfLists.GetByIndex(i);
for (int j = 0; j < list.Count; j++)
{
var key = (string) list.GetKey(j);
var value = (string) list.GetByIndex(j);
}
}
}
You already know how to get the key of your SortedList at an index i by using GetKey(i).
You can also get the value at that index by using GetByIndex(i). All of these can be found in the documentation, I suggest that you always read over it to see if there's anything in there that you can use.
Old Answer
I'm keeping this answer around in case it may be of use to the original poster.
You can use foreach loops to get the values of the 2nd list as KeyValuePairs:
var lists = new SortedList<string, SortedList<string, string>>
{
{
"foo",
new SortedList<string, string>
{
{ "0", "lol" },
{ "1", "skadoosh!" },
{ "2", "OMG!" }
}
}
};
foreach (var list in lists)
{
foreach (var kvp in list.Value)
{
Console.WriteLine("({0}, {1})", kvp.Key, kvp.Value);
}
}
Prefer Generic Collections to Non-Generic Ones
So, a couple of things to note with the above. I'm using the generic version of SortedList, i.e. SortedList<TKey, TValue>, because you get more type safety checks when accessing values then if you use the non-generic version. By using the generic version with explicit typing, you avoid having to explicitly cast types, like you would with the non-generic version (its methods return type object), like so:
var list = new SortedList();
list["foo"] = "bar";
string x = (string) list["foo"];
// vs generic
var list = new SortedList<string, string>();
list["foo"] = "bar";
string x = list["foo"];
It's generally best practice to use the generic versions of collections if you can. You should avoid the non-generic collections in most cases, you'll probably only see them in legacy code nowadays.
foreach loops with SortedList<TKey, TValue>
Okay, so the foreach loops allow you to get the values of a collection without having to specify an index or a key. So what are the values of a SortedList<TKey, TValue>? The values are KeyValuePair<TKey, TValue>:
SortedList<string, SortedList<string, string>> contains
KeyValuePair<string, SortedList<string, string>>.
SortedList<string, string> contains KeyValuePair<string, string>.
So in the first foreach loop, you get KeyValuePair<string, SortedList<string, string>>, and you want to access the list which is the value in that pair:
foreach (var list in lists)
{
foreach (var kvp in list.Value)
{
// Do stuff with kvp
}
}
So list.Value is a SortedList<string, string>, which contains (key, value) pairs of more strings. So you can just access each key and value with kvp.Key and kvp.Value.
To var or not to var? That is the question :P
You can also declare your foreach loops by specifying the item types explicitly instead of using var:
foreach (KeyValuePair<string, SortedList<string, string>> list in lists)
{
foreach (KeyValuePair<string, string> kvp in list.Value)
{
Console.WriteLine("({0}, {1})", kvp.Key, kvp.Value);
}
}
Which style you choose is up to you, they're both equivalent. Personally, I only use var when the type is obvious, otherwise it can be hard to tell what type is being used, especially if you're reviewing the code outside of Visual Studio, like in a Git diff or something. Another downside to using var instead of an explicit type is that you then can't declare object instances using interfaces, like this:
IDictionary<int, string> players = new SortedList<int, string>
{
{ 0, "John" }, { 1, "Dave" }
};
Declaring an object instance with an interface means that you'll be forced to only use methods that that interface declares, which can make it easier for you to switch implementations later. Of course, this is much less verbose:
var players = new SortedList<int, string> { { 0, "John" }, { 1, "Dave" } };
The use of var is a topic that has a history of a lot of debate.
I need a two column list like:
List<int,string> mylist= new List<int,string>();
it says
using the generic type System.collection.generic.List<T> requires 1 type arguments.
Depending on your needs, you have a few options here.
If you don't need to do key/value lookups and want to stick with a List<>, you can make use of Tuple<int, string>:
List<Tuple<int, string>> mylist = new List<Tuple<int, string>>();
// add an item
mylist.Add(new Tuple<int, string>(someInt, someString));
If you do want key/value lookups, you could move towards a Dictionary<int, string>:
Dictionary<int, string> mydict = new Dictionary<int, string>();
// add an item
mydict.Add(someInt, someString);
You could use an immutable struct
public struct Data
{
public Data(int intValue, string strValue)
{
IntegerData = intValue;
StringData = strValue;
}
public int IntegerData { get; private set; }
public string StringData { get; private set; }
}
var list = new List<Data>();
Or a KeyValuePair<int, string>
using Data = System.Collections.Generic.KeyValuePair<int, string>
...
var list = new List<Data>();
list.Add(new Data(12345, "56789"));
With the new ValueTuple from C# 7 (VS 2017 and above), there is a new solution:
List<(int,string)> mylist= new List<(int,string)>();
Which creates a list of ValueTuple type. If you're targeting .NET Framework 4.7+ or .NET/.NET Core, it's native, otherwise you have to get the ValueTuple package from nuget.
It's a struct opposing to Tuple, which is a class. It also has the advantage over the Tuple class that you could create a named tuple, like this:
var mylist = new List<(int myInt, string myString)>();
That way you can access like mylist[0].myInt and mylist[0].myString
Since your example uses a generic List, I assume you don't need an index or unique constraint on your data. A List may contain duplicate values. If you want to insure a unique key, consider using a Dictionary<TKey, TValue>().
var list = new List<Tuple<int,string>>();
list.Add(Tuple.Create(1, "Andy"));
list.Add(Tuple.Create(1, "John"));
list.Add(Tuple.Create(3, "Sally"));
foreach (var item in list)
{
Console.WriteLine(item.Item1.ToString());
Console.WriteLine(item.Item2);
}
Use C# Dictionary datastructure it good for you...
Dictionary<string, int> dict = new Dictionary<string, int>();
dict.Add("one", 1);
dict.Add("two", 2);
You can retrieve data from Ditionary in a simple way..
foreach (KeyValuePair<string, int> pair in dict)
{
MessageBox.Show(pair.Key.ToString ()+ " - " + pair.Value.ToString () );
}
For more example using C# Dictionary... C# Dictionary
Navi.
Not sure about your specific scenario, but you have three options:
1.) use Dictionary<..,..>
2.) create a wrapper class around your values and then you can use List
3.) use Tuple
List<Tuple<string, DateTime, string>> mylist = new List<Tuple<string, DateTime,string>>();
mylist.Add(new Tuple<string, DateTime, string>(Datei_Info.Dateiname, Datei_Info.Datum, Datei_Info.Größe));
for (int i = 0; i < mylist.Count; i++)
{
Console.WriteLine(mylist[i]);
}
For that, you could use a Dictionary where the int is the key.
new Dictionary<int, string>();
If you really want to use a list, it could be a List<Tuple<int,string>>() but, Tuple class is readonly, so you have to recreate the instance to modifie it.
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;
}
}
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.