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

How risky is a direct cast between compatible enums?

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

_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 中定义。我怀疑这会很快改变。

我问是因为我刚刚发现了一个不相关的错误,但在跟踪它的过程中,我发现 _viewModel.ServiceStatus 的值仍然始终为零。然后我将直接转换为以下内容,却发现错误仍然存​​在:

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

直接投射实际上工作正常,但这提出了一个对我来说非常重要的关于直接投射风险的问题。

在幕后,枚举只是整数(除非您另有说明)。所以从技术上讲,将枚举值转换为另一种没有该值字段的类型不是 "dangerous":

ServiceControllerStatus status = (ServiceControllerStatus)HostServiceStatus.Disabled;

status 的值将简单地为 8

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

您可以参考源枚举以使这些枚举之间的关系更加明显:

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

请注意,这些值是在编译时应用的;如果 ServiceControllerStatusHostServiceStatus 之外的另一个程序集中声明,并且 ServiceControllerStatus 发生更改,这些更改将不会反映在 [=15] 中=] 直到你重新编译它。