【问题标题】:Does adding enum values break binary compatibility?添加枚举值会破坏二进制兼容性吗?
【发布时间】:2012-09-24 19:42:38
【问题描述】:

想象一下 DLL 中的这个枚举。

public enum Colors
{
    Red,
    Green
}

添加枚举值会破坏二进制兼容性吗?如果我要更改它,现有的 EXE 会损坏吗?

public enum Colors
{
    Red,
    Green,
    Blue
}

我看到了this answer,但它似乎解决了插入一个值的情况。如果我将值添加到仅结束,可以吗?

【问题讨论】:

    标签: c# enums binary-compatibility


    【解决方案1】:

    应该没问题,假设您只追加到末尾。但是,破坏的风险来自于枚举值是隐式定义的,从 0 开始。因此,如果有人将这些值保存到数据库中,则可能会更改它们映射到的值。

    例如,如果您将枚举更改为:

    public enum Colors
    {
        Blue,
        Red,
        Green
    }
    

    任何将这些值存储在其数据库中的人都会看到曾经是红色的东西现在是蓝色的,而曾经是绿色的东西现在是红色的。

    理想情况下,您应该像这样定义您的枚举:

    public enum Colors
    {
        Red = 0,
        Green = 1
    }
    

    然后,当你添加一个新的,你应该有:

    public enum Colors
    {
        Red = 0,
        Green = 1,
        Blue = 2
    }
    

    这将有助于防止任何潜在的版本问题。

    【讨论】:

    • +1。如果可以的话,我也会给这张绿色支票。这是使枚举更坚固的明智方法。
    • 请注意,规范明确指出,如果您不指定任何值,它将从 0 开始并为每个值递增 1,因此它不像支持整数是未定义的行为第一种情况。您可以添加到末尾。
    • 对,但你必须将它添加到最后,否则它会中断。
    【解决方案2】:

    不,这不会破坏二进制兼容性(例如:程序集仍将加载等),因为枚举基本上是整数文字常量。在中间插入值显然是一个非常危险的想法,但您已经排除了它。

    但是,它可能会导致您需要防范的许多其他问题:

    • 某些代码(尤其是switch 语句)可能无法预测新值;从技术上讲,这也是一个问题,因为枚举没有经过值检查(枚举变量可以包含未定义的值)
    • 任何查询可用枚举的东西都会得到不同的结果
      • 特别是,如果存在使用特定客户端尚未预期的枚举的数据,则序列化和反序列化可能会意外失败

    【讨论】:

    • 太棒了。我能做些什么来抵抗破损?显然,如果我按照自己的方式进行操作,我就不会附加到枚举中,但是鉴于这种情况,最安全的方法是什么?对于 switch 语句(无意中的双关语),指定 default: 插槽是否会使其完全不受更改的影响?
    • @TheBuzzSaw 抵抗破坏的最好方法是不要将枚举用于任何你希望在时间结束之前保持不变的东西。
    • @Servy 同意...但是由于我现在被枚举困住了,你还有什么? ;)
    • @TheBuzzSaw 好吧,如果您知道使用它的地方范围有限,您可以验证没有人在做任何会受此更改影响的事情(即没有序列化,没有使用反射以枚举可能的值等)。您可以考虑从枚举切换到其他内容,因为这会破坏所有用户。它会让每个人都做出一些改变,但它会防止细微的错误被忽视。
    猜你喜欢
    • 2018-12-27
    • 2015-07-06
    • 2016-08-20
    • 2013-03-08
    • 2014-07-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多