在开发库以及框架的时候,持续维护会遇到兼容性的问题,如发现了旧版本有一些接口设计不合理,或者方法命名不符合逻辑等。此时如果直接更改原有的属性名或方法名甚至类名等,将会导致上层业务的开发者们在升级库之后构建不通过,因为缺少对应的方法。此时就需要上层业务的开发者们查阅文档才能了解如何应对升级之后带来的变动

在 dotnet 里面,可以使用 Obsolete 这个编译器分析辅助特性,给某个成员,如类和属性和方法事件等标记过时。这个 Obsolete 特性可以用来辅助库和框架开发者,在发生 API 变动时,可以保持兼容,或者提醒上层业务的开发者们如何应对

进行不兼容代码层 API 的变动,包括类名、属性名、方法名等所有公开的命名变更,以及命名空间的变更。还有删除成员带来的不兼容更改

而 Obsolete 特性标记,可以用来告知上层业务的开发者们当前成员已过时,同时在 Obsolete 特性标记上允许传入字符串,用于告诉上层业务的开发者们应当如何应对此变更。利用好这个特性,就可以让库和框架在变动 API 时,更好的保持兼容性,以及对上层业务的开发者们更加友好

用一个简单的例子说明 Obsolete 特性标记对 API 兼容性的用法

如一开始我创建了一个类 Foo 类,在这里面添加了 F1 属性,代码如下

    class Foo{public int F1 { set; get; }}

而随后,如需要做一个 API 命名变动的更改,如发现 F1 这个命名不清真,需要修改为 F2 这个命名。如果不做任何的兼容性处理,意味着更改的代码如下

    class Foo{public int F2 { set; get; }}

此时上层的开发者将会发现在升级了库或框架之后,将会因为找不到 Foo.F1 属性而构建不通过。有趣的是,上层业务的开发者们也不知道可以如何解决此构建不通过的问题

而如果依然保留 F1 这个属性,同时在属性上面标记 Obsolete 特性,告诉上层业务的开发者们应该如何更改,如以下代码

    class Foo{[EditorBrowsable(EditorBrowsableState.Never)][Obsolete("请使用 F2 代替")]public int F1{set => F2 = value;get => F2;}public int F2 { set; get; }}

那么此时的上层业务的开发者们在升级完成了库或框架之后,依然可以构建成功,只是存在一个警告。同时警告里面也告诉了上层业务的开发者们 请使用 F2 代替 这个解决方法

上面代码中,使用 F1 属性将不会占用任何内存量,因为整个 F1 属性都是对 F2 进行封装,在运行时优化里面又会进行内联,整体对性能影响将会特别小

通过在属性上面标记 Obsolete 特性的方式,可以做到在更改命名以及挪动方法和属性的时候,依然可以让上层业务能构建通过,同时也能告诉上层业务开发者们的更改方式

在上面代码中,依然添加了 EditorBrowsable 特性,通过这个特性可以告诉 VS 等 IDE 当前这个成员不应该出现在代码建议中。换句话说标记了 EditorBrowsable 特性将可以让开发者在使用到 Foo 类的时候,智能提示不会显示 F1 属性。通过标记 EditorBrowsable 特性可以保持 API 的整洁,对上层业务的开发者来说,不会因为整个类或命名空间里面充满了 Obsolete 的成员,而觉得很乱

而有一些方法因为之前版本设计的不合理,导致了用法上可能会出现坑,但是新版本没有一个能做到完全兼容的方案。此时也可以通过 Obsolete 特性,在特性的字符串里面告诉上层业务开发者们这个问题

而另一部分是在新版本上完全无法兼容的逻辑,例如更改了机制等,此时整个属性或方法等,都是无法实现的。可以保存一个空属性或方法等,同时标记 Obsolete 特性,只不过此时需要再添加一个参数,设置构建不通过,如以下代码

        [EditorBrowsable(EditorBrowsableState.Never)][Obsolete("请使用 F2 代替", error: true)]public int F1{// 无法实现set;// 无法实现get;}

使用 Obsolete 特性的做法对比直接删除属性或方法等的做法,优势在于可以让上层业务开发者们看到明确的放在 Obsolete 特性里面的字符串提示,可以解决很大部分的迁移成本。如上面的例子,在升级完成了库或框架之后上层业务开发者们看到构建不通过的提示内容,就可以自助完成迁移,而不需要再去寻找文档等

另一个话题是,通过本文的例子也可以让大家感受到公开的是属性而不是字段的一个优势。加入上面代码公开的是字段而不是属性,那么一些兼容性做法就非常难实现了,无论如何使用字段就一定占用了内存空间,此时的字段更新等行为都非常坑。而作为属性,是可以在内存上不存在的,只是公开出设置或获取方法,可以做到兼容

需要小心的一点是标记了 Obsolete 特性仅仅是编译器或 IDE 层面上的作用,而不是二进制 dll 或 exe 的作用,意味着如果在引用了旧版本的库或框架实现的应用,直接替换到新版本标记了 Obsolete 特性同时设置构建不通过的新库或框架的时候,此时的应用依然可以运行,只是运行过程中也许会出现不兼容的问题

也就是说 Obsolete 特性是给开发者用的,用于在写代码的时候的提示而已。即使在 Obsolete 特性同时设置构建不通过,也可以通过禁用错误提示的方法强行构建通过

本文代码放在 github 欢迎小伙伴访问

我搭建了自己的博客 https://blog.lindexi.com/ 欢迎大家访问,里面有很多新的博客。只有在我看到博客写成熟之后才会放在csdn或博客园,但是一旦发布了就不再更新

如果在博客看到有任何不懂的,欢迎交流,我搭建了 dotnet 职业技术学院 欢迎大家加入

如有不方便在博客评论的问题,可以加我 QQ 2844808902 交流


本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。欢迎转载、使用、重新发布,但务必保留文章署名林德熙(包含链接:http://blog.csdn.net/lindexi_gd ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请与我联系。

dotnet 使用 Obsolete 特性标记成员过时保持库和框架的兼容性相关推荐

  1. C#基础知识学习——特性(Conditional特性、Obsolete特性、自定义特性)(十六)

    特性:C#特性是指我们可以对类.以及C#程序集中的成员进行进一步的描述,比如我们写一个关于人的类Person,该类可以对人的属性以及某些行为(方法)进行描述.那么如果我们要对人类进行进一步描述呢,比如 ...

  2. 去掉idea中有些代码的黄色背景,去掉标记为过时的方法横线

    去掉idea中有些代码的黄色背景 alt+enter,翻译下拉的英文选项,点击>,选择 "disable"即可. 去掉标记为过时的方法横线 方法同上,需要知道下拉选项的英文含 ...

  3. 如何在时间紧迫情况下进行机器学习:构建标记的新闻 数据 库 开发 标记 网站 阅读1629 原文:How we built Tagger News: machine learning on a

    如何在时间紧迫情况下进行机器学习:构建标记的新闻 数据 库 开发 标记 网站 阅读1629  原文:How we built Tagger News: machine learning on a ti ...

  4. 字典的定义、字典的特性(成员操作符)

    一.字典的定义 代码块: users = ['user1','user2'] # passwd = ['123','456'] # print(zip(users,passwd)) # print(l ...

  5. 集合的创建、集合的特性(成员操作符、for循环)

    一.集合的创建 代码块: #集合里面的元素是不可重复的 s = {1,2,3,1,2,3,4,5} print(type(s)) print(s)s1 = set([]) print(type(s1) ...

  6. C++_类和对象_对象特性_成员变量占用对象内存_成员函数_静态成员函数_静态变量_都不占用对象内存_他们是分开存储的---C++语言工作笔记048

    然后我们来看c++中的,类的对象的大小,类中的成员变量和函数的存储问题. 首先我写个空类 然后在类外写个test01这个函数,然后 在main方法中调用这个test01这个函数

  7. 景深决定照相机什么特性_行政执法考试题库2017 2017摄影专业考试题库

    摄影专业的考试题内容包含什么?下面小编为大家整理哈尔滨学院2016年摄影专业考试题库.欢迎大家阅读参考! 简答: 1.景深: 答:当镜头对准某景物聚焦后,在该景物前后一定距离范围内的景物,也能在焦平面 ...

  8. java 方法过时_如何将方法标记为过时或已弃用?

    如何使用C#将方法标记为过时或过时? #1楼 最简单的方法是将ObsoleteAttribute作为方法的属性添加. 确保包括适当的解释: [Obsolete("Method1 is dep ...

  9. C#特性(属性)Attribute

    先明确一个概念: 元数据..NET中元数据是指程序集中的命名空间.类.方法.属性等信息.这些信息是可以通过Reflection读取出来的. 再来看个例子: #define BUG //#define ...

  10. Attribute特性定义及应用

    目录 一.前期准备 二.特性概念 三.特性案例 1.基础特性 -- 自定义 2.特性实战 -- 自定义 3.常用特性类 -- 官方 1.ObsoleteAttribute 2.AttributeUsa ...

最新文章

  1. python输入hello*3_Python3基础(一) Hello World
  2. DNS中实现父子域,以及授权和转发
  3. python哈夫曼编码注意_Python 算法(2) 哈夫曼编码 Huffman Encoding
  4. 81. 搜索旋转排序数组 II
  5. 一条SQL引发的“血案”:与SQL优化相关的4个案例
  6. gmail注册手机号不能用于验证_一个手机号码、辅助邮箱,可以注册绑定多少个gmail帐号?...
  7. DOM增删操作(创建删除表格)
  8. layui可以动态添加div吗_乳化剂是什么?可以添加到护肤品里吗?
  9. 使用python画二元二次函数(笔记)
  10. Vue+ bootStrap 实现员的增删改查 离职操作 全选单选
  11. 换脸算法 X2Face 详解
  12. 怎么添加计算机到网络共享中心,主编教您怎么设置局域网共享
  13. owt-conference 视频会议流程
  14. Mac M1 安装Maven
  15. 顺序表的基本操作(增删改查)——C语言
  16. 高性能低功耗服务器cpu,六核仅35W:AMD披露超低功耗服务器CPU
  17. centos系统mysql数据库搭建教程
  18. NVIDIA下载问题
  19. C. Electrification(尺取)
  20. 谷歌智能眼镜回归,针对商业用户售价999美元

热门文章

  1. (已解决)FutureWarning: Dropping of nuisance columns in DataFrame reductions (with ‘numeric_only=None‘)
  2. anti-wrinkle_Anti-wrinkle是什么意思
  3. SRVCC关键场景及Log分析
  4. C语言的函数到底是什么
  5. 【吐血整理-历时两个月,长达万字】FDTD Solutions学习笔记
  6. javascript history对象详解
  7. 放心吧,社区团购是兔子的尾巴长不了
  8. Unix/Linux系统中的inode总结
  9. 记录:web前端高德API获取天气服务
  10. css特殊符号代码以及用过使用方式。