10

Suppose we have the class X in version 1 of the assembly A.dll:

class X {
    SomeType Property { set; get; }
}

and then in version 2 of the assembly A.dll:

class X {
    SomeType Property { set; get; }
    SomeType OtherProperty { set; get; }
}

Now suppose we have a second assembly B.dll that loads A.dll and uses X. Will the addition of the property OtherProperty break the ABI? Will B.dll fail to use A.dll/X? If not, would the order of the declarations make any difference? If the properties had been virtual, had it made any difference?

I guess I'm really asking: what are the general ABI rules? I know changing interfaces after they have been published is a bad thing, but I really would like to be able to add properties in some instances, without adding subclasses.

linuxbuild
  • 15,170
  • 5
  • 55
  • 84
Jörgen Sigvardsson
  • 4,626
  • 2
  • 24
  • 50
  • 2
    See: A definite guide to API-breaking changes in .NET http://stackoverflow.com/questions/1456785/a-definite-guide-to-api-breaking-changes-in-net – Ani Jan 22 '11 at 08:41
  • How are you loading the DLLs? – Mark Byers Jan 22 '11 at 08:43
  • @Mark: I have third party clients that refer to some of my assemblies. I have a couple of classes that I want to extend with a few properties. I want to do so without requiring the third parties to recompile their assemblies. I could ask them nicely, but I'd rather not. It just adds more turnaround time... – Jörgen Sigvardsson Jan 22 '11 at 08:49

3 Answers3

11

The JIT compiler will spackle a lot of this over, also the source of the error message if the change was breaking.

You are however playing a very dangerous game called DLL Hell. The problem is not that they don't recompile their code, it is when they do. They will, eventually. If then there's a subtle mistake, somebody ran an old version of your installer, copied the wrong file, etcetera then all hell breaks loose. The code won't run and they'll have an impossible job figuring out why. This will happen long after you made the change, you won't have any way to guess what went wrong either and cannot help them.

Don't mess around with this, bump up [AssemblyFileVersion] and [AssemblyVersion]. Yes, they'll have to recompile when you change the latter one. Or use <bindingRedirect>, which is fine too, now there's a traceable record of it.

Btw: this happened in the .NET Framework too. WaitHandle.WaitOne(int) got added in a service pack but without an [AssemblyVersion] change. Programmers targeted .NET 2.0 but their code wouldn't run when the target machine had the original 2.0 installed. Very painful.

Hans Passant
  • 873,011
  • 131
  • 1,552
  • 2,371
7

Adding properties should be fine.

One case that will break is if you for example add something to the middle of an automatically numbered enum. For example if you have this code in your library:

enum Foo
{
   Bar,
   Qux
}

and you change it to this:

enum Foo
{
   Bar,
   Baz,
   Qux
}

Then you will also need to recompile any code like this:

if (foo == Foo.Qux)
{
    //  ...
}
Mark Byers
  • 719,658
  • 164
  • 1,497
  • 1,412
  • Suppose I have a method that returns a concrete class X. Would it break the ABI if I returned a refactored interface IX? I assume it will, because IX wasn't present in the first version of the assembly. – Jörgen Sigvardsson Jan 22 '11 at 08:52
  • @Jörgen Sigvardsson: It *should* be OK in most situations, but that there are corner cases where it might not work. For example if they are using reflection to inspect the class then they will be able to see any changes to the ABI and in theory it could break their code. – Mark Byers Jan 22 '11 at 09:21
  • @MarkByers Can you provide some reference of your answer above? – erick2red Aug 31 '15 at 18:29
  • you should only add enum in the end if you dont want to break existing code, that depends on that enum - https://stackoverflow.com/a/12716043/2719527 – T.Todua Jul 10 '19 at 13:33
2

It won't break compatibility if is just used by the assembly B. But it will break if the assembly B defines a class which implements the interface, because that class doesn't implement the newly introduced property.

CodesInChaos
  • 100,017
  • 20
  • 197
  • 251