Binary vs. Source compatibility

Binary Compatibility means that when something is updated, you continue to work without needing to even recompile. 

Source Compatibility means that you need to recompile to keep things working, but you don't have to actually change the sources.

One is not a superset of the other. Here are some examples in each combo.

Compatibility generally doesn't just mean that the change is discoverable, but that the change has some significant breaking implication that would cause a reasonably client to need to adjust their behavior. (Of course, you always find afterwards that's some important client did something unexpected and you need to compensate. Hence the heroics of the AppCompat folks). For example, with C# + reflection, any change is discoverable, so any change could technically break a client; but if a client breaks because they're relying on the names of private methods that you changed, they're hard-pressed to complain.


Yes Binary + Yes Source:

Renaming private methods. Changing a method body in a way that continues to behave the same.


Yes Binary, Not Source:

Adding new method overloads.  Since overload resolution is determined at compile time, adding new methods won't affect already-compiled binaries. But if you recompile, it's possible that you may bind to the new overloads.  (For example, see float.Equals)


Not Binary, Yes Source:

In this case, you just need to recompile your sources to keep working. The compiler will respond to the change in a corrective way. For example, consider removing a method overload. At a binary level, the method you're bound to is removed and so things fail. But if you recompile, the compiler may bind to another overload that's semantically equivalent, and so things keep working without you having to change any source.


Not Binary, Not Source:

A real breaking change. This requires clients to update their sources and recompile. For example, removing a method.