Will compiler optimize this code or will the collection be initialized after each method call?
private string Parse(string s)
{
var dict = new Dictionary<string, string>
{
{"a", "x"},
{"b", "y"}
};
return dict[s];
}
If answer is negative, I recommend to use this solution: Creating a constant Dictionary in C#
When such a question arises and you're not sure what the answer is, it's always good to look "under the hood".
This is the IL the compiler generated with the optimizer turned on:
Parse:
IL_0000: newobj System.Collections.Generic.Dictionary<System.String,System.String>..ctor
IL_0005: stloc.1 // <>g__initLocal0
IL_0006: ldloc.1 // <>g__initLocal0
IL_0007: ldstr "a"
IL_000C: ldstr "x"
IL_0011: callvirt System.Collections.Generic.Dictionary<System.String,System.String>.Add
IL_0016: ldloc.1 // <>g__initLocal0
IL_0017: ldstr "b"
IL_001C: ldstr "y"
IL_0021: callvirt System.Collections.Generic.Dictionary<System.String,System.String>.Add
IL_0026: ldloc.1 // <>g__initLocal0
IL_0027: stloc.0 // dict
IL_0028: ldloc.0 // dict
IL_0029: ldarg.1
IL_002A: callvirt System.Collections.Generic.Dictionary<System.String,System.String>.get_Item
IL_002F: ret
As you can see, it calls newobj
to allocate the Dictionary<K,V>
each time, loads both locals and calls Dictionary.Add
each time on both of them (which is the syntactical sugar equivalent of calling Add
) . It has no intimate knowledge with the type in order to cache the objects creation.
No, it will not. It has no intrinsic knowledge of what a Dictionary
is. For the compiler, it's just a normal class, so it doesn't know it could reuse the instance in this particular case.
This would be the proper way to do this:
public class Something
{
private static readonly Dictionary<string, string> _dict = new Dictionary<string, string>
{
{"a", "x"},
{"b", "y"}
}
private string Parse(string s)
{
return _dict[s];
}
}
This approach works because you know what the object does and you also know it's never modified.
Remember the following syntax:
var dict = new Dictionary<string, string>
{
{"a", "x"},
{"b", "y"}
}
Is just syntactic sugar for this:
var dict = new Dictionary<string, string>();
dict.Add("a", "x");
dict.Add("b", "y");
The only requirement to make this work with any class, is for the class to
IEnumerable
Add
method.You suggested to use a switch
statement, but the Dictionary
approach can be more flexible. Consider for instance you could want to use a different equality comparer (like StringComparer.OrdinalIgnoreCase
). It's better to let the Dictionary
handle this using the proper comparer than using something like switch(value.ToLowerInvariant())
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With