代码之家  ›  专栏  ›  技术社区  ›  ProfK

兼容枚举之间的直接转换风险有多大?

  •  2
  • ProfK  · 技术社区  · 10 年前

    我在两个枚举之间进行了以下直接转换:

    _viewModel.ServiceStatus = (HostServiceStatus)(HostController.Status);
    

    枚举为:

    public enum ServiceControllerStatus
    {
        Stopped = 1,
        StartPending = 2,
        StopPending = 3,
        Running = 4,
        ContinuePending = 5,
        PausePending = 6,
        Paused = 7,
    }
    public enum HostServiceStatus
    {
        // NB Do not ever change 1 to 6. These map directly to ServiceControllerStatus.
        NotInstalled = 0,
        Stopped = 1,
        StartPending = 2,
        StopPending = 3,
        Running = 4,
        ContinuePending = 5,
        PausePending = 6,
        Paused = 7,
        Disabled = 8
    }
    

    哪里 ServiceControllerStatus 是CLR的一部分,并在中定义 System.ServiceProcess 我怀疑这种情况很快就会改变。

    我这么问是因为我刚刚发现了一个无关的bug,但在追踪过程中,我发现 _viewModel.ServiceStatus 仍然总是值为零。然后我用以下内容替换了直接转换,结果发现bug仍然存在:

    var cs = HostController.Status;
    HostServiceStatus hs;
    Enum.TryParse(cs.ToString(), out hs);
    _viewModel.ServiceStatus = hs;
    

    直接演员实际上工作得很好,但这给我带来了一个非常重要的问题,关于直接演员的风险。

    1 回复  |  直到 10 年前
        1
  •  1
  •   C.Evenhuis    10 年前

    实际上,枚举只是int(除非您另有指定)。因此,从技术上讲,将枚举值转换为另一个没有该值字段的类型并不“危险”:

    ServiceControllerStatus status = (ServiceControllerStatus)HostServiceStatus.Disabled;
    

    的值 status 那么 8 .

    当然,危险已经存在于枚举声明的注释中:更改一个枚举的枚举值会导致应用程序仍然编译,但行为完全不同,甚至崩溃。

    您可以引用源枚举以使这些枚举之间的关系更加可见:

    public enum HostServiceStatus
    {
        NotInstalled = 0,
        Stopped = ServiceControllerStatus.Stopped,
        StartPending = ServiceControllerStatus.StartPending,
        ...
    

    请注意,这些值在编译时应用;如果 ServiceControllerStatus 在其他程序集中声明 HostServiceStatus ,以及 价值观 属于 服务控制器状态 这些更改将不会反映在 主机服务状态 直到您重新编译它。

    推荐文章