写点什么

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

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

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

关注

评论

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

【LeetCode】字符串相加Java题解

Albert

算法 LeetCode 11月月更

[力扣] 剑指 Offer 第二天 - 从尾到头打印链表

陈明勇

Go 数据结构与算法 力扣 11月月更

Docker——denied: requested access to the resource is denied问题以及解决方法

A-刘晨阳

Docker Linux 运维 11月月更

使用SQL加密函数实现数据列的加解密

华为云开发者联盟

大数据 后端 华为云 数据加密

使用 SAP Cloud Application Programming 编程模型开发一个图书管理 OData 服务

汪子熙

云原生 CAP SAP 企业级应用 11月月更

web技术分享| 日期选择限制组件二次封装

anyRTC开发者

Vue 前端 Web Element

HummerRisk V0.5.1 发布:新增对象存储、优化K8s 资源态势和资源拓扑等

HummerCloud

Kubernetes 云原生 云安全 云原生安全

count(*)查询性能很差?用这5招轻松优化

小小怪下士

Java 程序员 后端

多视角碰撞,探索 Serverless 企业落地更多可能性丨阿里云用户组厦门站

云布道师

阿里云 云原生

最佳实践 | 用腾讯云AI人像变换给自己一次“跨越年龄的体验”

牵着蜗牛去散步

人工智能 腾讯云 腾讯 腾讯云AI

Dive into TensorFlow系列(2)- 解析TF核心抽象op算子

京东科技开发者

tensorflow TF2 Tensor Op

OceanBase 首席科学家阳振坤博士入选2022 年度“CCF王选奖”

OceanBase 数据库

查看、校验、归档…带你掌握openGauss账本数据库

华为云开发者联盟

数据库 后端 华为云

PLC与SCADA的什么区别和联系

2D3D前端可视化开发

物联网 PLC 工业控制 web组态 SCADA

带你了解S12直播中的“黑科技”

华为云开发者联盟

云计算 后端 音视频 华为云 实时直播

比DataX快20%!SeaTunnel同步计算引擎性能测试全新发布

Apache SeaTunnel

spark DataX Seatunnel 数据集成平台 数据引擎

docker修改容器的端口、容器名、映射地址......

A-刘晨阳

Docker Linux 运维 11月月更

vue的几个提效技巧

yyds2026

Vue

数据库独角兽SingleStore:没有HTAP,机器学习和人工智能都是不切实际的

StoneDB

数据库 开源 HTAP StoneDB SingleStore

OKR之剑·实战篇03:OKR的跟踪需要有“自己”的节奏

vivo互联网技术

团队管理 OKR 目标管理

[力扣] 剑指 Offer 第二天 - 反转链表

陈明勇

Go 数据结构与算法 力扣 11月月更

彻底搞懂Vue虚拟Dom和diff算法

yyds2026

Vue

软件测试 | 测试人员必须掌握的测试用例

测试人

软件测试 自动化测试 测试开发 测试用例

实时云渲染vs本地渲染,哪个更好用?

Finovy Cloud

云渲染 实时云渲染

直播预告|OceanBase 社区版 4.0 全解析

OceanBase 数据库

技术分享 | 测试人员必须掌握的测试用例

霍格沃兹测试开发学社

Docker发布/上传镜像到dockerhub&&下载/拉取镜像&&删除dockerhub镜像

A-刘晨阳

Docker Linux 运维 11月月更

全国首个AIGC创作大赛开赛,创作者可靠“AI打工人”躺赚

科技热闻

计算机网络:以太网与IEEE 802.3

timerring

计算机网络 11月月更

SREWorks v1.3 版本发布 | 插件机制发布

阿里云大数据AI技术

大数据 运维 插件

阿里云产品经理刘宇:Serverless 的前世今生

云布道师

阿里云 Serverless 云原生

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