写点什么

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

  • 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:491955
用户头像

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

关注

评论

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

微博评论的高性能高可用计算架构设计

皓月

「架构实战营」

模块五

浮生若梦

最新版:Apache Pulsar 针对 Log4j 漏洞解决方案

Apache Pulsar

开源 架构 云原生 中间件 Apache Pulsar

架构实战营:模块三作业

Poplar

「架构实战营」

基于Javaweb,Mysql图书管理系统

叫练

如何自学编程?

DaemonStone

程序员 程序员人生 自学编程 经验总结 大学生毕业

Jenkins Pipeline: 并发执行

夏兮。

jenkins pipeline jenkins高级用法 parallel

潘娟:从女工程师转变成开源商业化Infra公司创始人,痛并快乐着

腾源会

数据库 开源 Apache ShardingSphere 开源商业化

【重构前端知识体系之HTML】讲讲对HTML5的一大特性——语义化的理解

归子莫

html html5 前端 语义化 1月月更

SpringBoot 实战:加载和读取资源文件

看山

classpath SpringBoot 2 1月月更

ReactNative进阶(二十五):ScrollView 滚动视图组件详解

No Silver Bullet

React Native ScrollView 1月月更

外网打点,内网渗透

网络安全学海

黑客 网络安全 信息安全 渗透测试 安全漏洞

19 Prometheus之告警的艺术

穿过生命散发芬芳

Prometheus 1月月更

Spring中的单例模式使用

JavaEdge

1月月更

InnoDB 引擎了解(双写机制)

Ayue、

MySQL 数据库 1月月更

一个BPMN流程示例带你认识项目中流程的生命周期

华为云开发者联盟

工作流 项目 BPM BPMN Activiti框架

架构实战营 模块五作业

Jude

架构实战营

30人的产研团队如何高效协同?

阿里云云效

阿里云 DevOps 云原生 研发管理 研发团队

架构训练营模块五作业

沈益飞

架构训练营 架构师训练营 4 期

如何真正学习Go 语言[翻译]

宇宙之一粟

Go 学习方法 Go 语言 1月月更

使用 VSCode 调试 Electron 主进程代码

编程三昧

Electron 1月月更

「架构实战营」模块五《如何设计业务高性能高可用计算架构》作业

DaiChen

作业 模块五 「架构实战营」

Apache Pulsar 针对 Log4j2 漏洞 (CVE-2021-44228) 的解决方案

Apache Pulsar

开源 云原生 中间件 Apache Pulsar log4j2

Spring 都在用的技术,你确定不过来看看?2️⃣

XiaoLin_Java

1月月更

让创新触手可及,阿里云容器服务 ACK 发行版开放免费下载

阿里巴巴云原生

阿里云 云原生 容器服务 ACK

算法大佬Carl的面试简历长啥样?同款模板让你脱胎换骨!

博文视点Broadview

一个cpp协程库的前世今生(二十一)协程重分配

SkyFire

c++ cocpp

【架构师训练营】模块五作业

樰巳-堕~Horry

架构实战营 「架构实战营」

阿里云开源业内首个应用多活项目 AppActive,与社区共建云原生容灾标准

阿里巴巴云原生

阿里云 开源 高可用 云原生 容灾

面试突击17:HashMap除了死循环还有什么问题?

王磊

Serverless,引领云计算下一个阶段

华为云开发者联盟

MySQL 云计算 Serverless 华为云 FunctionGraph

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