Reputation: 12574
I have a possible implementation scenario where I need a dictionary object that will take 3 variables. A dialect, a query name and a query string. I should note at this stage that writing a separate class object is not an option.
My question is which of the following would perform better.
A) A single dictionary object that takes the first two variables in as a composite key e.g. "dialect,queryname" and the 3rd variable as the value.
private Dictionary<string, string>
B) A dictionary object that has another dictionary object as the value so the first variable would be the key of the primary dictionary object, the 2nd variable would be the key of the 2nd dictionary object and finally the 3rd variable would be the value of the second dictionary object.
private Dictionary<string, Dictionary<string, string>>
Seems obvious but the compiler is a mysterious thing so thought I should ask you guys.
Thanks
Upvotes: 3
Views: 933
Reputation: 113222
This is not a matter of performance, as the two have completely different semantics.
The first gives you a way to use one object to find another object.
The second gives you a way to use one object to find another object, in which you can use yet another object to find a third object.
There is slightly different functionality in terms of how these can be later extended.
Most generally, I'd use Dictionary<Tuple<string, string>, string>
. This would give me a composite key that is clearly a composite key.
Actually, that's not true, I'd create a new class. How is that not an option? Still, if it was homework and "do not create a new class" was part of the question, I'd use Dictionary<Tuple<string, string>, string>
.
Edit:
class DialectQuery : IEquatable<DialectQuery>
{
public Dialect{get;private set}
public Name{get;private set;}
public DialectQuery(string dialect, string name)
{
Dialect = dialect;
Name = name;
}
public bool Equals(DialectQuery other)
{
return other != null && Name == other.Name && Dialect == other.Dialect;
}
public override bool Equals(object other)
{
return Equals((object)other);
}
public override int GetHashCode()
{
int dHash = Dialect.GetHashCode();
return (dHash << 16 | dHash >> 16) ^ Name.GetHashCode();
}
}
So far it behaves exactly the same as Tuple. Now though if I get a change request that dialects must be case-insensitive but query names case-sensitive, or that dialects are codes and therefore require invariant comparison but names are human-input and therefore require culture-aware comparison, or anything else, I've got two simple changes to make.
YAGNI doesn't apply, it's not coding a massive object "in case you need it", it's defining a good "okay, I probably don't need it, but if I do it'll go here" point.
Upvotes: 0
Reputation: 125
Just mucking around for my own amusement ..
Dictionary<string, string> md1 = new Dictionary<string,string>();
Dictionary<string, Dictionary<string, string>> md2 = new Dictionary<string, Dictionary<string, string>>();
Stopwatch st = new Stopwatch();
st.Start();
for (int i = 0; i < 2000000; i++)
{
md1.Add(i.ToString(), "blabla");
}
st.Stop();
Console.WriteLine(st.ElapsedMilliseconds);
st.Reset();
st.Start();
for (int i = 0; i < 2000000; i++)
{
md2.Add(i.ToString(), new Dictionary<string, string>());
}
st.Stop();
Console.WriteLine(st.ElapsedMilliseconds);
Console.ReadLine();
output:
831
1399
Upvotes: 2
Reputation: 529
Why don't you use:
Dictionary<string, KeyValuePair<string, string>>
I think is better than both.
Upvotes: 0
Reputation: 39007
As long as you're sure that the key "dialect,queryname" is unique, I think the first solution is faster. In the second one, you'd have to do one more dictionary lookup, which is probably more costly than a string concatenation.
Upvotes: 2