编译器会优化集合初始化?

时间:2014-11-14 08:31:33

标签: c# .net dictionary compiler-optimization

编译器会优化此代码还是在每次调用方法后初始化集合?

private string Parse(string s)
{
    var dict = new Dictionary<string, string>
    {
        {"a", "x"},
        {"b", "y"}
    };

    return dict[s];
}

如果答案是否定的,我建议使用此解决方案:Creating a constant Dictionary in C#

3 个答案:

答案 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;这无论如何 - 我非常怀疑将会是这种情况。

虽然你可能会争辩说这个特定的代码可以被优化,但它实际上是一个边界情况,这在编译时并不是那么简单。给你一个反例 - 如果你的一个字符串文字是另一个类的成员怎么办?如果你有一个自定义词典(并且对现有的词典类没有特殊处理)在构造函数中做了一些时髦的事情会怎么样?