【问题标题】:Why should I make the underlying type of an Enum Int32 instead of byte?为什么我应该使用 Enum Int32 而不是字节的基础类型?
【发布时间】:2012-04-30 07:24:09
【问题描述】:

给定以下枚举:

public enum Operations_PerHourType : byte
{
    Holes = 1,
    Pieces = 2,
    Sheets = 3,
    Strips = 4,
    Studs = 5
}

当我运行微软代码分析工具时,它告诉我:

CA1028:Microsoft.Design:如果可能,将基础类型设为“Enums.Operations_PerHourType”System.Int32 而不是“byte”。

它永远不会有超过几个可能的值,所以我将它声明为一个字节。为什么他们会推荐使用 int32?未来可扩展性的更多价值?还是有性能提升?

【问题讨论】:

  • 为什么要关心存储是字节还是整数?您尝试强制使用字节的动机是什么?
  • 我没有,直到我运行了 Microsoft 代码分析工具。它建议使用 Int32。我很好奇为什么。我最初使用 byte 是因为我认为它对性能会更好。空间更小。
  • @DavidHeffernan 你为什么不关心?好奇有什么不好?
  • @MrLister 这不是重点。我试图引出的是明确指定byte 的动机。我没有写,所以我关心或不关心的东西既不在这里也不在那里。显然凯文在乎。他写了byte。我没说他不应该在乎。我没有说关心是错误的。我的评论没有通过任何判断。我只是问为什么?好奇有什么不好?
  • 我希望int 的性能优于byte,因为它具有更好的对齐属性

标签: c# .net enums


【解决方案1】:

看看MSDN的原因。

摘录如下:

枚举是一种值类型,它定义了一组相关的命名 常数。默认情况下,System.Int32 数据类型用于存储 恒定值。即使您可以更改此基础类型,它也是 在大多数情况下不需要或不推荐。请注意,没有 通过使用以下数据类型可实现显着的性能提升 小于 Int32。如果不能使用默认数据类型,则 应使用符合公共语言系统 (CLS) 的积分之一 类型、字节、Int16、Int32 或 Int64,以确保 枚举可以在符合 CLS 的编程中表示 语言。

【讨论】:

    【解决方案2】:

    在某些特定情况下,缩小基础类型会带来一些优势,例如与性能相关或在与非托管代码交互时强制使用特定的内存布局。

    考虑这个示例:

    using System;
    
    public enum Operations_PerHourType //   : byte
    {
        Holes = 1,
        Pieces = 2,
        Sheets = 3,
        Strips = 4,
        Studs = 5
    }
    
    class Program
    {
        static void Main()
        {
            long before = GC.GetTotalMemory(false);
            var enums = new Operations_PerHourType[10000];
            long after = GC.GetTotalMemory(false);
    
            Console.WriteLine(after - before);
            // output  (byte): 12218 (I'm using Mono 2.8)
            // output (Int32): 40960
        }
    }
    

    此代码消耗大约 40 KB 的堆。现在将底层类型指定(取消注释)byte 并重新编译。哇。突然间,我们只需要大约 10 KB。

    像这样压缩内存有时可能会使程序变慢,而不是变快,具体取决于特定的访问模式和数据大小。除了进行一些测量并尝试推广到其他可能的情况外,没有办法确定。较小数据的顺序遍历通常更快。

    但是,仅仅因为它通常是可能的而且有时是至关重要的而养成指定窄类型的习惯并不是一个好主意。由于周围更广泛的数据类型的内存对齐,内存节省很少实现。由于需要额外的指令来屏蔽填充字节,因此性能要么相同,要么稍差。

    正如另一个答案已经说得很好,跟随运行时优化的 Int32 人群,直到您必须开始分析和解决应用程序中的实际内存消耗。

    【讨论】:

    • 很好地反驳了其他 cmets 中的一些错误信息。
    【解决方案3】:

    根据文档,使用字节而不是 INT32 不会提高性能。除非有理由这样做,否则他们建议不要更改它。基本思想是 .NET 针对在许多场景中使用 INT32 进行了优化,他们选择它作为枚举是有原因的。通过更改它,您不会在您的场景中得到任何东西,所以为什么要麻烦。

    http://msdn.microsoft.com/en-us/library/ms182147.aspx

    这还讨论了如何优化 .NET 以使用 32 位整数:.NET Optimized Int32

    【讨论】:

    • 优化使用 INT32 的不是 .NET,而是底层 CPU,最显着的原因是汇编指令操作数的寄存器大小/大小——这恰好是 32 位的 32 位位系统。如果值的大小不同,则需要对齐/填充,并且为此需要额外的 cpu 周期。有趣的是,您链接的线程中提到了这一点。最有可能的开销是最小的。关键是,出于性能原因使用 BYTE 而不是 INT32 实际上会产生相反的效果。每种 HL 语言都是如此。
    • @SaschaHennig - 该线程提供了良好但不完整的背景。另请阅读:stackoverflow.com/questions/1054657/… 了解为什么基于 Int32 的枚举有时会在结构布局中占用多达 8 个字节,这是 Microsoft 做出的与性能相关的双刃决策,如果您知道自己是什么,您可以覆盖它正在做。负责的不是框架或硬件。他们一起工作。
    • @Jirka Hanika - 有趣的阅读,谢谢。任何 HL 语言都只能在其运行的硬件环境中优化变量(或任何东西)的使用。仍然不是框架或硬件负责,归根结底是编码器。
    猜你喜欢
    • 2011-06-19
    • 2016-02-05
    • 2017-09-29
    • 1970-01-01
    • 1970-01-01
    • 2016-05-23
    • 2013-06-07
    • 1970-01-01
    • 2012-07-12
    相关资源
    最近更新 更多