关于.net:C#接口破坏,ABI

C# interface breakage, ABI

假设我们在组件A.dll的版本1中有class X

1
2
3
class X {
    SomeType Property { set; get; }
}

然后在组件的版本2中A.dll中:

1
2
3
4
class X {
    SomeType Property { set; get; }
    SomeType OtherProperty { set; get; }
}

现在假设我们有第二个组件B.dll,加载A.dll并使用x。添加属性OtherProperty会破坏abi吗?B.dll是否不能使用A.dllX?如果没有,声明的顺序会有什么不同吗?如果属性是虚拟的,它有什么区别吗?

我想我真的在问:ABI的一般规则是什么?我知道在接口发布后更改接口是一件坏事,但我真的希望能够在某些情况下添加属性,而不添加子类。


JIT编译器将在这一点上抹去许多污点,如果更改正在中断,也将是错误消息的来源。

然而,你正在玩一个非常危险的游戏,叫做DLL地狱。问题不在于他们不重新编译代码,而是在他们重新编译代码的时候。他们最终会的。如果出现了一个微妙的错误,有人运行了一个旧版本的安装程序,复制了错误的文件,等等,那么所有的地狱都将被释放。代码无法运行,他们将无法找到原因。这种情况在你做出改变后很长时间内就会发生,你也不会有任何方法去猜测出什么地方出了问题,也无法帮助他们。

不要搞得一团糟,把[assemblyfileversion]和[assemblyversion]调高。是的,当您更改后一个时,它们必须重新编译。或者使用,也可以,现在有了一个可追踪的记录。

顺便说一句:这也发生在.NET框架中。WaitHandle.WaitOne(int)已添加到Service Pack中,但未更改[assemblyVersion]。程序员以.NET 2.0为目标,但当目标计算机安装了原始的2.0时,他们的代码将无法运行。非常痛苦。


添加属性应该可以。

例如,如果在一个自动编号的枚举的中间添加一些内容,就会中断。例如,如果库中有此代码:

1
2
3
4
5
enum Foo
{
   Bar,
   Qux
}

你把它改成:

1
2
3
4
5
6
enum Foo
{
   Bar,
   Baz,
   Qux
}

然后您还需要重新编译如下代码:

1
2
3
4
if (foo == Foo.Qux)
{
    //  ...
}


如果只是由组件B使用,它不会破坏兼容性。但是,如果程序集B定义了一个实现接口的类,它将中断,因为该类不实现新引入的属性。