c#编译时提高兼容性_幻像类型提高了编译时的安全性

c#编译时提高兼容性

介绍

使用幻像类型是一种非常简单的技术,可用于提高代码的编译时安全性。 有很多潜在的用例,其复杂性程度各不相同,但是即使幻像类型的轻量级使用也可以显着提高编译时的安全性。 幻像类型只是带有未使用类型参数的参数化类型。 例如:

public class MyPhantomType<T> {public String sayHello() {return 'hello';}// other methods/fields that never refer to T
}

该示例类的类型参数为T,但实际上从未在代码中使用。 乍一看,这似乎没有什么用,但事实并非如此! 幻像类型的所有对象实例都带有类型信息,因此该技术可用于“标记”带有一些可在编译时检查的额外信息的值。 当然,我们可以通过编写不带泛型的代码来随时逃避键入操作,但是应该不惜一切代价避免这种情况。 某些语言(例如Scala)完全不允许删除类型参数,因此使用Scala时,您将始终必须完全保留类型信息。

示例用例和实现

幻像类型最简单,最有用的用例之一是数据库ID。 如果我们有一个典型的三层(数据,服务,Web)Java Web应用程序,则可以通过在架构的“端点”以外的任何地方用幻像类型替换原始id来获得大量的编译时安全性。 因此,数据层会将原始ID放入数据库查询中,而Web层可能会从外部资源(例如HTTP参数)获取原始ID,但是否则,我们始终会处理幻像类型。 在此示例中,我假设数据库ID类型始终为64位长数字。 首先,我们需要将由所有“实体类”实现的标记器接口,该接口应受幻像类型id机制支持:

public interface Entity {Long getId();
}

该标记接口的唯一目的是将我们的幻像型id限制为一组标记的类,并提供将在实现中使用的getId方法。 实际的幻像类型是单个id值的不可变容器。 type参数表示id的“目标类型”,这使得可以以编译时安全的方式在不同实体的id值之间进行区分。 我喜欢将此类称为Ref(参考的简写),但这只是个人选择。

@Value
@RequiredArgsConstructor(AccessLevel.PRIVATE)
public final class Ref<T extends Entity> implements Serializable {public final long id;  public static <T extends Entity> Ref<T> of(T value) {return new Ref<T>(value.getId());}public static <T extends Entity> Ref<T> of(long id, Class<T> clazz) {return new Ref<T>(id);}@Overridepublic String toString() {return String.valueOf(id);}}

此示例类使用Project Lombok中的@Value和@RequiredArgsConstructor批注。 如果您不使用Lombok,请手动添加构造函数,getter,equals和hashCode实现(或在下面查找完整的实现)。 请注意,类型参数T永远不会在任何地方使用。 这也意味着您在运行时无法知道Ref的类型,但这通常不是必需的。

使用示例实现

现在,我们将在可能的情况下将原始ID替换为Refs。 例如,我们可以有一个将用户添加到组中的服务级别方法:

void addUserToGroup(long userId, long groupId);
// without parameter names
void addUserToGroup(long, long);// VSvoid addUserToGroup(Ref<User> userRef, Ref<Group> groupRef);
// without parameter names
void addUserToGroup(Ref<User>, Ref<Group>);

现在,当我们要调用此方法时,将始终需要Ref对象而不是原始的long值。 在此示例中,有两种获取参考值的方法。

  1. 如果您有实际对象的实例,请调用Ref.of(object)。 这是除Web以外的其他层中最常见的方法
  2. 如果您有原始ID,并且知道目标类型,请调用Ref.of(id,TargetType.class)。 如果原始ID来自外部,则通常在Web层中需要这样做

为了从Ref中提取原始ID值,您可以阅读该字段或使用吸气剂。 通常仅在数据库查询构建之前才需要这样做。

总结思想

为了了解裁判的好处,请尝试考虑以下情况:

  • 如果您在采用不同类型ID的方法调用中更改参数顺序,会发生什么情况? (例如我们的addUserToGroup)
  • 如果更改数据库ID的类型(例如Integer-> Long或Long-> UUID)会发生什么?
  • 如果您经常具有与id相同类型但不是id的方法参数,那么您将有多大可能出现运行时错误? 例如,如果您具有整数ID,并且在同一方法中混合了ID和某种列表索引

在所有这些情况下,使用Refs都可以确保在代码不正确的地方出现编译时错误。 在典型的代码库中,这是不费吹灰之力的巨大胜利。 编译时的安全性降低了重构的成本和难度,这使得维护代码库变得非常容易和安全。

数据库ID只是幻像类型的简单示例。 其他典型用例包括某种状态机(例如,Order <InProcess>,Order <Completed>与仅Order对象),以及某种类型的值单位信息(例如,LongNumber <Weight>,LongNumber <Temperature>与longs) 。

Ref <T>实现(无Lombok)

public final class Ref<T extends Entity> implements Serializable {public final long id;public static <T extends Entity> Ref<T> of(T value) {return new Ref<T>(value.getId());}public static <T extends Entity> Ref<T> of(long id, Class<T> clazz) {return new Ref<T>(id);}@Overridepublic String toString() {return String.valueOf(id);}private Ref(long id) {this.id = id;}public long getId() {return this.id;}@Overridepublic int hashCode() {return (int) (id ^ (id >>> 32));}@Overridepublic boolean equals(Object o) {if (this == o)return true;if (o == null || o.getClass() != this.getClass())return false;Ref<?> other = (Ref<?>) o;return other.id == this.id;}
}

参考: Gekkio的技术博客博客中的JCG合作伙伴 Joonas Javanainen提出了幻像类型 , 提高了编译时安全性 。

翻译自: https://www.javacodegeeks.com/2013/02/increased-compile-time-safety-with-phantom-types.html

c#编译时提高兼容性

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/349660.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何查看电脑显卡配置_3080显卡电脑配置清单(3700X/10700)

3080显卡昨天就解禁评测了&#xff0c;因为最近的老铁都很期待装3080的机器&#xff0c;我这边做了一些整理&#xff0c;方便各位老铁3080配置有综合的了解。3080显卡售价更加详尽的3080厂家整理可以参考&#xff1a;3080公版哪里买&#xff1f;&#xff08;所有厂家整理&#…

问题 1074: 数字整除

题目描述定理&#xff1a;把一个至少两位的正整数的个位数字去掉&#xff0c;再从余下的数中减去个位数的5倍。当且仅当差是17的倍数时&#xff0c;原数也是17的倍数 。 例如&#xff0c;34是17的倍数&#xff0c;因为3-20-17是17的倍数&#xff1b;201不是17的倍数&#xff0c…

GWT HTTP请求替代

由于多种原因 &#xff0c;许多GWT用户放弃了RPC机制&#xff0c;这是GWT提供的调用后端的标准方法。 他们发现&#xff0c;在GWT RequestBuilder与其他可能不适合其应用程序模型的外部库之间迷失了许多 。 这篇文章的目的是通过GWT中众所周知的HTTP / Rest库&#xff0c;以使情…

极限中0除以常数_基本不等式中常用公式百度作业帮

1. 基本不等式中常用公式基本不等式中常用公式&#xff1a;(1)√((ab)/2)≥(ab)/2≥√ab≥2/(1/a1/b)。(当且仅当ab时&#xff0c;等号成立)(2)√(ab)≤(ab)/2。(当且仅当ab时&#xff0c;等号成立)(3)ab≥2ab。(当且仅当ab时&#xff0c;等号成立)(4)ab≤(ab)/4。(当且仅当ab时…

NOIP模拟测试24「star way to hevaen·lost my music」

star way to heaven 题解 大致尝试了一下并查集,记忆化搜索,最小生成树 最小生成树是正解,跑最小生成树然后找到最大的值 欧几里德距离最小生成树学习 prim楞跑 至于为什么跑最小生成树不是跑最大生成树,你跑最大生成树连的边可能会^%$&$%!# 感性理解手膜吧,我理解但说不清…

NOIP模拟测试25「字符串·乌鸦喝水·所陀门王的宝藏(陀螺王)」

字符串 题解 没看出catalan怎么办 dp打表啊! 考虑大力dp拿到30分好成绩!顺便收获一张表 打表发现$C_{nm}^{m}-C_{nm}^{m-1}$ 仔细观察然后发现其实就是之前的网格那个题 那么我们回顾一下网格那个题 先看最简单的nm情况 求左下角走到右上角方案数,不能经过中间那条线 考虑大力容…

stackexchange_通过Spring Social推特StackExchange –第1部分

stackexchange本文将介绍一个快速的附带项目-一个自动从各种Q&#xff06;A StackExchange网站上发布热门问题的机器人&#xff0c;例如StackOverflow &#xff0c; ServerFault &#xff0c; SuperUser等。我们将为StackExchange API构建一个简单的客户端&#xff0c;然后进行…

bandizip最后一个无广告版本_【软件来了】这是个无广告的旧版知乎

近两天有新加入粉丝团队的小伙伴在询问G先生旧版App的事情&#xff0c;文章已发过很久&#xff0c;但是知乎的旧版本还是头一次分享给大家&#xff0c;所以G先生就找到了两个版本的旧版知乎&#xff0c;知乎V3.1和知乎V3.9这两个知乎都支持在最高的系统&#xff0c;没有广告也没…

NOIP模拟测试26「嚎叫响彻在贪婪的机房·主仆见证了 Hobo 的离别·征途堆积出友情的永恒」...

题目比较神仙&#xff0c;注意是题目神仙 贪婪暗示贪心&#xff0c;堆积暗示堆优化$\%\%\%\%\%\%\%$ 两个乱搞$$一个堆优化$dp$ 嚎叫响彻在贪婪的机房 题解 对于一个序列来说只要他们差的$gcd$不为$1$就可以构成等差数列 例如 $2$ $4$ $16$ $2$与$4$差$2$ $4$与$16$差$1…

渴望订阅– RxJava常见问题解答

在教学和指导RxJava以及撰写本书之后 &#xff0c;我注意到某些领域尤其成问题。 我决定发布一些简短的提示&#xff0c;以解决最常见的陷阱。 这是第一部分。 Observable和Flowable本质上是惰性的。 这意味着无论您在Flowable放置了多么繁琐或长时间运行的逻辑&#xff0c;仅…

WPScan高级用法和定制

自定义扫描选项 WordPress作为一个广泛使用的内容管理系统&#xff08;CMS&#xff09;&#xff0c;为用户提供了丰富的自定义选项&#xff0c;使其能够根据特定需求创建个性化的网站。其中一个重要的自定义选项是自定义扫描选项&#xff0c;它允许用户对WordPress网站进行深度…

r语言中正定矩阵由于误差不正定_R语言之数据处理(一)

在上一篇小文中&#xff0c;提到了关于R语言导入数据的一些方法&#xff0c;之后的重点就转向了数据的处理上。数据处理其实在整个数据分析项目中所占用的时间是比较多的&#xff0c;所以根据处理的目的不同&#xff0c;也有不同的处理方法。在R语言中&#xff0c;我通常会将数…

【chromium】 渲染显示相关概念

DRM(Direct Rendering Manager) DRM 由两个部分组成&#xff1a;一是 Kernel 的子系统&#xff0c;这个子系统对硬件 GPU 操作进行了一层框架封装。二是提供了一个 libdrm 库&#xff0c;里面封装了一系列 API&#xff0c;用来进行图像显示。 说到这里&#xff0c;其实这么理解…

ASP.NET Core MVC 之区域(Area)

区域&#xff08;Area&#xff09;是一个 ASP.NET MVC 功能&#xff0c;用于将相关功能组织为一个单独的命名空间&#xff08;用于路由&#xff09;和文件结构&#xff08;用于视图&#xff09;。使用区域通过向控制器和操作添加 一个路由参数&#xff08;area&#xff09;来创…

esp32 arduino adc_英雄联盟手游射手出装怎么出 adc英雄出装推荐

2020-11-02 18:06:31 角色扮演 人气值&#xff1a;加载中...英雄联盟手游adc怎么出装备&#xff1f;英雄联盟手游虽然没有上线国服和台湾服&#xff0c;但是我们已经有很多热心的玩家在外服中研究出了各种射手的玩法&#xff0c;那么adc要怎么出装呢&#xff1f;小编已经准备…

camel.js_Camel 2.11 –没有Spring的Camel Web应用程序

camel.js在撰写本文时&#xff0c;我们刚刚向即将到来的Apache Camel 2.11添加了一个新组件&#xff0c;该组件允许使用Camel运行Web应用程序&#xff0c;而不必依赖Spring Framework来加速Camel。 或与此相关的任何其他第三方框架。 有点as愧地说&#xff0c;在2013年&#x…

宅男计划

题解 $dp$不行考虑三分 发现单峰 1.理性打表,得到单峰 2.感性思考,你会发现你买食物次数越多,你钱数越少,你买的好食品更多,你买食物次数越少,你钱数越多,然而你必须买一些价格贵保质期长弥补次数少. 单峰,我们三分就完了(其实也可以模拟退火,然而我参数爆炸了一直60分) 那么$c…

.net 后台 下载 图片_特殊的 “图片软件” !

01 引语简单的图片处理软件我说过不少&#xff0c;像windows自带的图片编辑、在线处理图片的稿定设计、或者ps的一些插件。虽然我知道这类工具型软件的文章&#xff0c;大多数小伙伴都只是随便看一眼&#xff0c;心里默念 “咦&#xff0c;好像有用&#xff01;”&#xff0c;…

流操作中的noException

本文介绍了一些简单的编码实践。 没什么好看的。 在StackOverflow上也进行了讨论。 您只是将一个庞大而复杂的循环重构为一个更具可读性的流表达式&#xff0c;而忘记了某些方法调用引发了异常。 包含此代码的方法将引发此异常&#xff0c;该异常在方法头中声明。 您不想在此级…

optimize table 需要多久_吉林市政工程资质新办需要多久

七。 暖通空调专业&#xff1a;水暖工程&#xff0c;建筑环境与设备&#xff0c;环境工程&#xff0c;暖通空调&#xff0c;供暖和通风与空调&#xff0c;制冷和空调&#xff0c;水暖&#xff0c;供暖和通风&#xff0c;HVAC&#xff0c;公共设备安装。如何申请第三级土木工程资…