C#为对象分配枚举值

时间:2017-03-30 14:44:35

标签: c# performance object enums box

在我们代码的某些地方,我们将枚举值赋给对象变量(例如:object value = DayOfWeek.Sunday)。我在思考枚举底层类型的行是int,所以为什么不使用(int)然后调用.ToString()来避免装箱。为了我的幸福,它似乎避免拳击(我检查了IL代码),但令我惊讶的是,这部分代码花了更多的时间来执行和分配更多的内存。我使用BenchmarkDotNet工具来测试性能差异。以下是代码示例

1)返回枚举值,发生装箱(下面的IL代码)

public object AssingEnumToObject()
    {
        return DayOfWeek.Sunday;
    }

  // Code size       7 (0x7)
  .maxstack  8
  IL_0000:  ldc.i4.0
  IL_0001:  box        [mscorlib]System.DayOfWeek
  IL_0006:  ret

2)使用(int),仍然可以理解拳击。

public object AssingEnumIntToObject()
        {
            return (int)DayOfWeek.Sunday;
        }

// Code size       7 (0x7)
  .maxstack  8
  IL_0000:  ldc.i4.0
  IL_0001:  box        [mscorlib]System.Int32
  IL_0006:  ret

3)使用(int)然后使用ToString()。现在为需要对象返回类型的方法返回它的字符串。在IL中没有装箱但是调用了Int32.ToString()方法。

public object AssingEnumIntStringToObject()
        {
            return ((int)DayOfWeek.Sunday).ToString();            
        }

  // Code size       10 (0xa)
  .maxstack  1
  .locals init ([0] int32 V_0)
  IL_0000:  ldc.i4.0
  IL_0001:  stloc.0
  IL_0002:  ldloca.s   V_0
  IL_0004:  call       instance string [mscorlib]System.Int32::ToString()
  IL_0009:  ret

令我惊讶的是,BenchmarkDotNet工具显示,方法3(AssingEnumIntStringToObject)需要更长时间并分配更多内存。

Results of BenchmarkDotNet tool 我在这里错过了什么?是否因为CSharp语言规范中的这个规则“从任何枚举类型到类型System.Enum”?如果是这样,这是如何工作的?

请解释一下。谢谢。

编辑:

感谢@JonSkeet和@Craig的答案。我没有考虑创建字符串引用的成本。我现在明白了。

1 个答案:

答案 0 :(得分:1)

方法3花费的时间更长,因为它正在向ToString添加函数调用并分配和分配字符串,所有这些都需要额外的时间。

方法3占用更多内存,因为它正在分配字符串。与装箱转换一样,这是添加引用(指针大小),但它也添加了字符串本身。字符串至少是int的大小:至少,它有一个大小的计数器(我相信四个字节)加上字符的缓冲区(对于你的情况最少一个字符)。因此,这需要额外内存的两倍以上,而其他两个内存最多只添加一个引用(指针大小)。