我想尽可能多地收集有关.NET/CLR中的API版本控制的信息,特别是API更改如何影响或不 destruct 客户端应用程序.首先,我们来定义一些术语:

API change-类型(包括其任何公共成员)的公开可见定义的更改.这包括更改类型和成员名称、更改类型的基类型、在类型的已实现接口列表中添加/移除接口、添加/移除成员(包括重载)、更改成员可见性、重命名方法和类型参数、添加方法参数的默认值、添加/移除类型和成员的属性,以及添加/移除类型和成员的泛型类型参数(我是否遗漏了什么?).这不包括对成员机构的任何更改,也不包括对私有成员的任何更改(即,我们不考虑反映).

Binary-level break-API更改会导致根据旧版本的API编译的客户端程序集可能不会随新版本一起加载.示例:更改方法签名,即使它允许以与以前相同的方式调用(即:void以返回类型/参数默认值重载).

Source-level break-一个API更改,导致编写的现有代码针对旧版本的API进行编译,可能无法使用新版本进行编译.然而,已经编译的客户端程序集仍能像以前一样工作.示例:添加一个新的重载,这可能会导致以前明确的方法调用出现歧义.

Source-level quiet semantics change-一个API更改,导致编写的现有代码针对较旧版本的API悄悄地更改其语义,例如通过调用不同的方法.但是,代码应该继续编译,没有警告/错误,以前编译的程序集应该像以前一样工作.示例:在现有类上实现新接口,导致在重载解析期间 Select 不同的重载.

最终目标是对尽可能多的 destruct 性和安静的语义API更改进行编目,并描述 destruct 的确切影响,以及哪些语言受其影响,哪些语言不受其影响.对后一种语言进行扩展:虽然有些更改会普遍影响所有语言(例如,向接口添加新成员会 destruct 该接口在任何语言中的实现),但有些更改需要非常特定的语言语义才能发挥作用,以获得突破.这通常涉及方法重载,通常与隐式类型转换有关.即使对于符合CLS的语言(即至少符合CLI规范中定义的"CLS使用者"规则的语言),这里似乎也没有任何方法来定义"最小公分母"——尽管如果有人在这里纠正我的错误,我将不胜感激,所以这将不得不逐个语言.最感兴趣的自然是随之而来的.开箱即用:C#、VB和F#;但其他一些,如IronPython、IronRuby、Delphi Prism等也与此相关.越是极端的情况,它就越有趣——删除成员之类的事情是不言而喻的,但方法重载、可选/默认参数、lambda类型推断和转换运算符之间的微妙交互有时会非常令人惊讶.

以下是一些例子:

添加新的方法重载

种类:源代码级别中断

受影响的语言:C#、VB、F#

更改前的API:

public class Foo
{
    public void Bar(IEnumerable x);
}

更改后的API:

public class Foo
{
    public void Bar(IEnumerable x);
    public void Bar(ICloneable x);
}

示例客户端代码在更改前工作,更改后中断:

new Foo().Bar(new int[0]);

添加新的隐式转换运算符重载

种类:源代码级别中断.

受影响的语言:C#、VB

不受影响的语言:F#

更改前的API:

public class Foo
{
    public static implicit operator int ();
}

更改后的API:

public class Foo
{
    public static implicit operator int ();
    public static implicit operator float ();
}

示例客户端代码在更改前工作,更改后中断:

void Bar(int x);
void Bar(float x);
Bar(new Foo());

注意:F#没有被 destruct ,因为它没有任何语言级别的重载运算符支持,无论是显式还是隐式的,都必须作为op_Explicitop_Implicit方法直接调用.

添加新的实例方法

种类:源代码级别的安静语义更改.

受影响的语言:C#、VB

不受影响的语言:F#

更改前的API:

public class Foo
{
}

更改后的API:

public class Foo
{
    public void Bar();
}

遭受静默语义更改的示例客户端代码:

public static class FooExtensions
{
    public void Bar(this Foo foo);
}

new Foo().Bar();

注意:F#没有被 destruct ,因为它没有ExtensionMethodAttribute的语言级支持,并且需要将CLS扩展方法称为静态方法.

推荐答案

更改方法签名

种类:二进制级中断

受影响的语言:C#(最有可能是VB和F,但未经测试)

更改前的API

public static class Foo
{
    public static void bar(int i);
}

更改后的空气污染指数

public static class Foo
{
    public static bool bar(int i);
}

更改前工作的客户机代码示例

Foo.bar(13);

.net相关问答推荐

为什么Linq中的运算符逻辑不匹配结果,当值为0或在VB. NET中没有

类似于字典但没有值的 C# 数据 struct

在 C# 中获取 log4net 日志(log)文件

比较 C# 中的双精度值

每第 N 个字符/数字拆分一个字符串/数字?

如何防止和/或处理 StackOverflowException?

.NET 世界是否有 Maven 替代方案或端口?

为什么递归调用会导致不同堆栈深度的 StackOverflow?

什么是 project.lock.json?

HashSet 是否保留插入顺序?

从 Windows 窗体打开 URL

Iif 在 C# 中等效

如何在 C# 中以编程方式安装 Windows 服务?

如何防止任务的同步延续?

在任务中捕获异常的最佳方法是什么?

Environment.GetFolderPath(...CommonApplicationData) 在 Vista 上仍然返回C:\Documents and Settings\

在 .NET 中获取默认打印机的最佳方法是什么

找不到 System.Windows.Media 命名空间?

可以从 C# 调用 C++ 代码吗?

如何为我的 C# 应用程序创建产品密钥?