写点什么

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

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

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

关注

评论

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

一部好看过武侠小说的热血互联网史!

博文视点Broadview

FunTester框架Redis性能测试之list操作

FunTester

redis 性能测试 测试框架 压力测试 FunTester

2021年公有云市场的5大趋势

云计算

网络攻防学习笔记 Day144

穿过生命散发芬芳

高可用 9月日更

国庆高质量出行,可视化开启智慧旅游

ThingJS数字孪生引擎

大前端 物联网 可视化 旅游 数字孪生

低代码应用:软件开发的一体化最新形态!

优秀

低代码

乘着汽车智能化的浪潮,“汽车人”的职业方向选择(三)

SOA开发者

软件定义汽车 车载控制单元

Alibaba内部“Java架构核心宝典”来袭,全新技术限时开源

Java 编程 程序员 架构 面试

千万级数据迁移与分表的技术方案-企业产品实战

谙忆

Java 后端 分库分表 引航计划

玩转TypeScript工具类型(下)

有道技术团队

typescript 大前端 网易有道

阿里,快手,拼多多等7家大厂Java面试真题,Java面试题高级

Java 程序员 后端

主机安全是什么意思?安全体检包含哪些方面?

行云管家

运维 服务器 主机 主机安全 安全体检

幻读是啥,会有什么问题?如何解决?

Java MySQL 数据库 面试 后端

mydumper备份工具介绍与使用

Simon

MySQL

堡垒机作用之事后审计详细讲解-行云管家

行云管家

运维 网络安全 运维审计 事后审计

JavaScript进阶(七)call, apply, bind

Augus

JavaScript 9月日更

Linux用户密码管理

在即

9月日更

为什么不推荐Python初学者直接看项目源码

Felix

Python 编程 开发 Programing 阅读代码

二十不惑的年纪,我简直走了狗屎运(4面拿字节跳动offer)

Java 程序员 架构 面试 计算机

通俗易懂 即时通讯初学者入门 WhatsApp技术架构

OpenIM

作为一线技术人员,如何更好地提升自己

谙忆

管理 成长 引航计划

与springcloud整合的框架源码读取入口

Java 编程 架构 微服务

iOS开发面试拿offer攻略之数据结构与算法篇附加安全加密

iOSer

ios 数据加密 iOS面试 iOS逆向 iOS算法

深入理解掌握零拷贝技术

Linux服务器开发

网络协议 零拷贝 Linux服务器开发 Linux内核 用户态

Tapdata 实时数据中台在智慧教育中的实践

tapdata

CSS 轻松制作 SVG 动画

devpoint

css3 SVG 9月日更

测试开发之前端篇-CSS层叠式样式表

禅道项目管理

CSS html

对Python爬虫编写者充满诱惑的网站,《可爱图片网》,瞧人这网站名字起的

梦想橡皮擦

9月日更

Percolator模型及其在TiKV中的实现

vivo互联网技术

数据库 Percolator 分布式,

基于Tensorflow + Opencv 实现CNN自定义图像分类

华为云开发者联盟

tensorflow KNN OpenCV CNN

金融级分布式事务解决方案DTC

tom

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