9 月 13 日,2025 Inclusion・外滩大会「开源嘉年华」正在限量报名中! 了解详情
写点什么

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

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

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

关注

评论

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

Linux之find命令的参数详解

入门小站

Linux

模块八作业

Presley

网络攻防学习笔记 Day71

穿过生命散发芬芳

网络攻防 7月日更

我为什么要学习业务建模?

escray

学习 极客时间 7月日更 如何落地业务建模

PowerShell 正则表达式

耳东@Erdong

PowerShell 7月日更

密码你真的了解吗

卢卡多多

7月日更

Hadoop 入门教程

若尘

大数据 hadoop

全面了解Java并发编程基础!超详细!

程序员的时光

Java 并发编程

你以为的你以为未必是你以为的

Bruce Talk

敏捷 随笔 Agile 引导和教练

性能框架哪家强—JMeter、K6、locust、FunTester横向对比

FunTester

性能测试 接口测试 测试框架 测试开发

ACM金牌选手整理的【LeetCode刷题顺序】

编程熊

Java 面试 算法 面经 笔试

模块一作业

Always

架构实战营

架构实战营 模块八课后作业

iProcess

架构实战营

🏆【CI/CD技术专题】「Maven插件Docker系列」使用Maven插件构建Docker镜像的方法

码界西柚

Docker maven 7月日更 Plugin

在线脑图思维导图生成工具

入门小站

工具

【Flutter 专题】90 图解 Dart 单线程实现异步处理之 Future (一)

阿策小和尚

Flutter 小菜 0 基础学习 Flutter Android 小菜鸟 7月日更

实时音视频技术全栈攻略|寻找C站宝藏

liuzhen007

音视频 7月日更

性能测试框架对比初探

FunTester

性能测试 接口测试 测试框架 测试开发

架构训练营模块 1 作业 - 1班助教

听闻

网络攻防学习笔记 Day70

穿过生命散发芬芳

网络攻防 7月日更

Javascript 的工作原理:引擎、运行时和调用堆栈概述

devpoint

JavaScript V8 7月日更

京东智造云:在世界人工智能大会上,听到的工业智能生长的声音

脑极体

Go 学习笔记之 结构体

架构精进之路

Go 语言 7月日更

推荐系统的未来发展(三十三)

Databri_AI

价值观 推荐系统

公司内部使用的数仓开发规范

白贺BaiHe

数据仓库 开发规范 数仓规范 7月日更

暑假期间快手将重点整治平台:短视频平台如何完善内容审核机制

石头IT视角

【LeetCode】基于时间的键值存储Java题解

Albert

算法 LeetCode 7月日更

Kats-Facebook最新开源的时序分析工具

好孩子

只更新代码,然后发布版本:基于 Serverless Devs 原子化操作阿里云函数计算

Serverless Devs

Apache Flink 漫谈系列 —— 概述

云祁

flink 7月日更

领域驱动设计到底在讲什么?

escray

学习 极客时间 7月日更 如何落地业务建模

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