编译器会优化此代码还是在每次调用方法后初始化集合?
private string Parse(string s)
{
var dict = new Dictionary<string, string>
{
{"a", "x"},
{"b", "y"}
};
return dict[s];
}
如果答案是否定的,我建议使用此解决方案:Creating a constant Dictionary in C#
答案 0 :(得分:13)
当出现这样的问题并且您不确定答案是什么时,总是很好看#34;
这是编译器在打开优化器时生成的IL:
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
正如您所看到的,它每次调用newobj
来分配Dictionary<K,V>
,每次都会加载本地人并调用Dictionary.Add
(这是调用Add
)的语法糖等价物。它对类型没有熟悉的知识,以便缓存对象的创建。
答案 1 :(得分:6)
不,它不会。它没有Dictionary
是什么的内在知识。对于编译器,它只是一个普通的类,所以它不知道可能在这种特殊情况下重用该实例。
这是执行此操作的正确方法:
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];
}
}
这种方法很有效,因为你知道对象的作用,而且你也知道它永远不会被修改。
请记住以下语法:
var dict = new Dictionary<string, string>
{
{"a", "x"},
{"b", "y"}
}
这只是语法糖:
var dict = new Dictionary<string, string>();
dict.Add("a", "x");
dict.Add("b", "y");
使用任何类进行此操作的唯一要求是该类
IEnumerable
Add
方法。您建议使用switch
语句,但Dictionary
方法可以更灵活。例如,考虑您可能想要使用不同的相等比较器(如StringComparer.OrdinalIgnoreCase
)。让Dictionary
使用适当的比较器处理此问题比使用switch(value.ToLowerInvariant())
之类的东西更好。
答案 2 :(得分:2)
不,C#因为它赢得了优化&#39;这无论如何 - 我非常怀疑将会是这种情况。
虽然你可能会争辩说这个特定的代码可以被优化,但它实际上是一个边界情况,这在编译时并不是那么简单。给你一个反例 - 如果你的一个字符串文字是另一个类的成员怎么办?如果你有一个自定义词典(并且对现有的词典类没有特殊处理)在构造函数中做了一些时髦的事情会怎么样?