15

Imagine this enum in a DLL.

public enum Colors
{
    Red,
    Green
}

Does adding enum values break binary compatibility? If I were to change it, would existing EXEs break?

public enum Colors
{
    Red,
    Green,
    Blue
}

I saw this answer, but it seemed to address the case of inserting a value. If I add values to the end only, is that OK?

Community
  • 1
  • 1
TheBuzzSaw
  • 8,648
  • 5
  • 39
  • 58

2 Answers2

24

No, this doesn't break binary compatibility (in as much as: the assembly will still load etc), because enums are basically integer literal constants. Inserting values in the middle is obviously a really dangerous idea, but you've already excluded that.

However, it can cause a number of other issues that you need to guard against:

  • some code (switch statements in particular) may not anticipate the new values; technically this was an issue before too, since enums are not value-checked (enum variables can contain undefined values)
  • anything that queries the available enums is going to get different results
    • in particular, serialization and deserialization may fail unexpectedly if there is data using enums that aren't yet expected by the particular client
Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • 1
    Awesome. What can I do to resist breakage? Obviously, if I had it my way, I wouldn't be appending to enums, but given the circumstances, what is the safest way to approach this? In the case of switch statements (pun unintended), would having the `default:` slot specified harden it against changes at all? – TheBuzzSaw Oct 03 '12 at 20:13
  • 1
    @TheBuzzSaw The best way to resist breakage is to not use enums for anything that you expect to not remain the same until the end of time. – Servy Oct 03 '12 at 20:17
  • @Servy Agreed... but since I'm stuck with enums right now, what else you got? ;) – TheBuzzSaw Oct 03 '12 at 20:20
  • 1
    @TheBuzzSaw Well, if you know that there is a limited scope of places where it's used, you could just verify that nobody is doing anything that would be affected by this change (i.e. no serialization, no using reflection to enumerate the possible values, etc). You could consider switching from an enum to something else knowing that it will break all users. It would make everyone make some change, but it would prevent subtle bugs from going under the radar. – Servy Oct 03 '12 at 20:22
4

It should be fine, assuming you only append to the end. However, the risk of breaking would come from the fact that the enum values are implicitly defined, starting at 0. So if someone is persisting the values to a DB, you risk changing which values they map to.

As an example, if you changed your enum to be:

public enum Colors
{
    Blue,
    Red,
    Green
}

Anyone who stored these values in their DBs would see that things that were once Red, are now Blue, and what was Green is now Red.

Ideally, you should define your enum like so:

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

And then, when you add a new one, you should have:

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

This will help prevent any potential versioning issues.

Jeffrey Lott
  • 7,171
  • 6
  • 28
  • 28
  • +1. I'd give this a green check too if I could. This is a smart way to make the enums sturdier. – TheBuzzSaw Oct 03 '12 at 20:20
  • Note that the specs specifically state that, if you don't specify any values, it will start at 0 and increment by one for each value, so it's not like the backing integer is undefined behavior for the first case. You can just add to the end. – Servy Oct 03 '12 at 20:23
  • Right, but you have to add it to the end or else it breaks. – Jeffrey Lott Oct 03 '12 at 20:26