写点什么

使用扩展方法对调用进行验证

  • 2009-03-27
  • 本文字数:1347 字

    阅读完需:约 4 分钟

利用 C# 3.0 提供的扩展方法技术,可以为已经编译好的程序集类型增加新的方法,从而应对新的扩展。除了在可扩展性方面所具有的优势之外,如果能够合理地结合泛型与类型推断,扩展方法还可以有效降低代码的重复,提高程序的可重用性。例如,这样的方法实现:
public class CustomerDAL
{
public IEnumerable FindCustomers(string roleName)
{
return from customer
in context.Customer
where customer.RoleName.Equals(roleName)
select customer;
}
} 调用如下方法,可能抛出 NullReferenceException 异常:

Customer customer = new CustomerDAL().FindCustomers(Role.Admin).First(); 我们需要对返回结果进行验证,如果返回为 null,则可以抛出自定义异常,或者创建一个空对象,例如:

public IEnumerable FindCustomers(string roleName)
{
IEnumerable customers = from customer
in context.Customer
where customer.RoleName.Equals(roleName)
select customer;
if (customers == null)
{
throw new MyException(“Cann’t find the customers.”);
}
return customers;
} 如果系统有许多方法都需要对返回结果进行验证,则这样的验证逻辑就会充斥在各个方法体中,既不利于重用,也会对未来的修改造成极大的阻碍。当然,我们可以引入 Null Object 模式来替代对 null 值的判断逻辑,但这种方式仍然需要为多种类型定义不同的 Null Object 类型。

Craig Andera 在其博客文章中提出使用扩展方法对调用进行验证。他写道:

NullReferenceException 异常会抛出,但是我们希望有更具体的异常信息。因此,我们编写了如下的扩展方法:

public static T OrThrow(this T obj, Exception e) {
if (obj == null) {
throw e;
}
return obj;
}

利用 OrThrow 扩展方法,则之前的调用方式可以修改为:

Customer customer = new CustomerDAL().FindCustomers(Role.Admin).OrThrow(new MyException(“Can’t find Customer”)).First();

Craig Andera 提出:

OrThrow 扩展方法对于你所要调用的类型而言是通用的,并且它返回了该类型,所以你可以将其插入到表达式链中,而不会丢失智能感应功能。并且因为类型推断功能,实际上并不需要指定具体的类型。

也就是说,OrThrow 扩展方法可以应用到任何类型上,因此它可以在各种类型上重用非空验证甚至是调用验证。借鉴这一思想,我们还可以利用此方法默认实现对象实例的创建,以避免抛出 NullReferenceException 异常,例如:
public static T Instance(this T obj) where T:new()
{
if (obj == null)
{
obj = new T();
}

return obj;
}

由于 Instance 扩展方法中的类型参数 T 需要创建实例,因此必须添加 new() 约束。所以该扩展方法存在一定的局限,例如无法应用在之前的 IEnumerable 类型上。但对于如下的方法却非常有效:
public class ListObject
{
public List Foo()
{
return null;
}
}

通过 Instance 扩展方法,可以安全地调用 List 的相关属性和方法,例如 Count 属性:
Console.WriteLine(new ListObject().Foo().Instance().Count);

控制台打印出来的结果为 0。如果没有 Instance 扩展方法,则会抛出 NullReferenceException 异常。

作为 C# 3.0 增加的新特性,扩展方法在大量项目中得到了广泛地应用,但绝不仅仅是提高可扩展性这么简单。在进行项目开发时,若能适当地考虑使用扩展方法,说不定会带来出奇制胜的效果。

2009-03-27 21:491903
用户头像

发布了 109 篇内容, 共 44.1 次阅读, 收获喜欢 14 次。

关注

评论

发布
暂无评论
发现更多内容

ThreadLocal 慌不慌?

叫练

JVM ThreadLocal 引用 软引用

精选2021互联网大厂Java核心面试题库(金三银四面试必备)

比伯

Java 编程 架构 面试 程序人生

LiteOS:剖析时间管理模块源代码

华为云开发者联盟

时间管理 时间 LiteOS huawei 任务

uni-app跨端开发H5、小程序、IOS、Android(六):uni-app事件绑定

黑马腾云

微信小程序 uni-app 大前端 iOS Developer 3月日更

EGG公链强势来袭!去中心化社交革命先驱EFTalk

币圈那点事

java好还是嵌入式好?做IT开发该如何选择

cdhqyj

Java 编程 发展 开发 嵌入式

基于感染原理判断图的连通性算法

大奎

图算法 子图 连通性

Flink SQL 在网易云音乐的产品化实践

Apache Flink

flink

书单|互联网企业面试案头书之架构师篇

博文视点Broadview

架构

一文了解数据库资源管理技术

华为云开发者联盟

数据库 存储 GaussDB(DWS) 资源管理

对于移动开发,人工智能的到来意味着什么?

故胤道长

人工智能 机器学习 ios开发 Android开发

【Doris Weekly】2020.03.08~2021.03.21

ApacheDoris

【Doris Weekly】

揭秘盒马鲜生,如何打破收益增长天花板!

博文视点Broadview

分布式任务 + 消息队列框架 go-queue

万俊峰Kevin

微服务 分布式任务 消息队列 Go 语言

跟随报文,开启一段奇妙之旅

华为云开发者联盟

报文 Windows主机 路由器 Linux主机 路由表

开发也要防“沉迷”?IDEA插件教程详解

京东科技开发者

Java 开发 IntelliJ IDEA

墨天轮精选:数据库问答集萃第一期-2021

墨天轮

MySQL 数据库 sql dba

基于NA公链(Nirvana)的应用和NAC公链社区共识探究公链的发展未来

区块链第一资讯

vivo 应用商店推荐系统探索与实践

vivo互联网技术

架构 推荐系统 服务器

数据库周刊62丨央企2021年数据库成交公告,国产占90%;流数据库HStreamDB开源;MySQL主从双写导致数据丢失;Oracle 19c升级最佳实践;PG日常工作分享;MySQL MGR运维指南;SQL语法手册……

墨天轮

MySQL 数据库 sql postgre

力扣(LeetCode)刷题,简单题(第15期)

不脱发的程序猿

LeetCode 编程之路 28天写作 算法面经 3月日更

【IstioCon 2021】最佳实践:从Spring Cloud 到 Istio

华为云原生团队

开源 Kubernetes 云原生 istio 服务网格

Cobar SQL审计的设计与实现

捉虫大师

Disruptor Skywalking cobar 数据库中间件

力扣(LeetCode)刷题,简单题(第16期)

不脱发的程序猿

面试 LeetCode 28天写作 算法面经 3月日更

彩色图像的二值化,取经之旅第 6 天

梦想橡皮擦

28天写作 3月日更

技术实践丨Prometheus+Grafana搭建HBase监控仪表盘

华为云开发者联盟

开源 Grafana Prometheus HBase 开源数据库

【LeetCode】位1的个数Java题解

Albert

算法 LeetCode 3月日更

【遇见Doris】基于Apache Doris的小米增长分析平台实践

ApacheDoris

终于有阿里高工把SpringBoot+SpringCloud+Docker+MQ整合在一起了

Java架构追梦

Java 架构 微服务 springboot SpringCloud

微信聊天记录里的文件又失效了?试试这个文件同步开源项目吧

HelloGitHub

开源 文件传输 Go 语言

字节跳动单点恢复功能及 Regional CheckPoint 优化实践

Apache Flink

flink

使用扩展方法对调用进行验证_.NET_张逸_InfoQ精选文章