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

ast*_*tef 8 .net c# dictionary compiler-optimization

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

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

    return dict[s];
}
Run Code Online (Sandbox Code Playgroud)

如果答案是否定的,我建议使用此解决方案:在C#中创建常量字典

Yuv*_*kov 13

当出现这样的问题并且你不确定答案是什么时,看看"引擎盖下"总是好的.

这是打开优化器时生成的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    
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,它调用每次newobj分配,Dictionary<K,V> 每次都加载本地和调用Dictionary.Add(这是与调用相当的语法糖Add).它对类型没有熟悉的知识,以便缓存对象的创建.

  • 此检查的结果可能随时发生变化.理由是不允许编译器执行此操作要好得多. (2认同)

Luc*_*ski 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];
    }
}
Run Code Online (Sandbox Code Playgroud)

这种方法有效,因为您知道对象的作用,并且您也知道它永远不会被修改.

请记住以下语法:

var dict = new Dictionary<string, string>
{
    {"a", "x"},
    {"b", "y"}
}
Run Code Online (Sandbox Code Playgroud)

这只是语法糖:

var dict = new Dictionary<string, string>();
dict.Add("a", "x");
dict.Add("b", "y");
Run Code Online (Sandbox Code Playgroud)

使这个适用于任何类的唯一要求是该类

  • 实行 IEnumerable
  • 有一个公共Add方法.

您建议使用switch语句,但Dictionary方法可以更灵活.例如,考虑您可能想要使用不同的相等比较器(如StringComparer.OrdinalIgnoreCase).Dictionary使用适当的比较器来处理这个比使用类似的东西更好switch(value.ToLowerInvariant()).