写点什么

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

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

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

关注

评论

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

运维服务体系构建

阿泽🧸

运维体系 6月月更

大家的 Hexo 博客都还好吗?

jrwng

Hexo

Django API 开发:博客系统的权限管理

宇宙之一粟

django 6月月更

【100个 Unity实用技能】| 游戏中使技能或装备跟随角色环绕,持续旋转

呆呆敲代码的小Y

【100个 Unity踩坑小知识点】| Unity控制物体持续指向某个方向

呆呆敲代码的小Y

理解 Java 中的 NumberFormatException 异常

HoneyMoose

见自身,见天地:华为,将ICT技术变成绿色未来的支点

脑极体

【100个 Unity踩坑小知识点】| 在编辑器中绘制正方体虚线、球体虚线(Gizmos 辅助线框)

呆呆敲代码的小Y

【100个 Unity踩坑小知识点】| Unity中的 Development build 详细解析

呆呆敲代码的小Y

使用IDE并不是懒癌表现

Geek_99967b

小程序 小程序容器

【愚公系列】2022年06月 面向对象设计原则(一)-单一职责原则

愚公搬代码

6月月更

华为云AppCube带你5分钟开发微信小程序

乌龟哥哥

6月月更

vue指令-2

小恺

6月月更

【100个 Unity踩坑小知识点】| Unity 使用Quaternion.AngleAxis随机一个方向

呆呆敲代码的小Y

【网络编程知识】什么是Socket?概念及原理分析

呆呆敲代码的小Y

红利、辛苦钱、利润和工资【读书笔记】

FunTester

如何写好技术博客

卢卡多多

技术 博客 6月月更

数据类型

Jason199

js 数据类型 6月月更

在线JADE转HTML工具

入门小站

工具

数据库每日一题---第4天:从不订购的客户

知心宝贝

数据库 程序员 前端 后端 6月月更

InfoQ 极客传媒 15 周年庆征文|聊聊 Kafka:Kafka 如何保证一致性

老周聊架构

kafka 架构 云原生 6月月更 InfoQ极客传媒15周年庆

【100个 Unity踩坑小知识点】| Unity中的 碰撞盒检测 Physics.OverlapBox、OverlapCapsule、OverlapSphere

呆呆敲代码的小Y

软件设计本质

GalaxyCreater

架构 设计模式 架构师 系统 软件设计

linux中删除特殊文件

入门小站

Linux

this和super的用法与区别

写代码两年半

继承 super javase this 6月月更

在线文本右边批量删除字符工具

入门小站

工具

NFT赛道或进入聚合时代,OKALEIDO成BNB Chain上的首个NFT聚合平台

股市老人

【100个 Unity实用技能】| 游戏中获取鼠标点击的坐标,并将游戏对象移动到鼠标的点击位置

呆呆敲代码的小Y

互联网电商项目天花板,从立项到交付快速落地,真正帮你解决大型互联网项目经验欠缺的短板

Java全栈架构师

程序员 面试 项目 架构设计 程序员进阶

答应我:监听日志文件变化的这三种方法你一定要会!推荐第三种!

Java全栈架构师

Java 程序员 面试 IDEA 代码人生

【100个 Unity踩坑小知识点】| Unity调用API ,动态获取Android权限,附带所有Android权限表格

呆呆敲代码的小Y

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