阿里云「飞天发布时刻」2024来啦!新产品、新特性、新能力、新方案,等你来探~ 了解详情
写点什么

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

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

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

关注

评论

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

全链路压测系列(三):技术改造和测试验证

老张

性能测试 全链路压测

56 K8S之Kubernetes监控

穿过生命散发芬芳

k8s 28天写作 12月日更

PassJava 开源 (七) :Spring Cloud 整合 OpenFeign 实现声明式远程调用

悟空聊架构

28天写作 passjava 悟空聊架构 12月日更 openfeign

架构训练营 -- 模块四

LJK

#架构训练营

区块链在电动车产业中的角色

CECBC

Golang中的runtime包

liuzhen007

28天写作 12月日更

一文搞懂ReentrantLock的公平锁和非公平锁

Ayue、

ReentrantLock 公平锁 非公平锁

Linux之whereis命令

入门小站

Linux

学习方法

Tiger

28天写作

Tinder系统架构

俞凡

架构 大厂实践 Tinder

Springboot国际化消息和源码解读

DoneSpeak

Java spring springboot

微服务架构 | 怎样解决超大附件分片上传?

码农架构

微服务架构 springboot 断点续传 SpringCloud 大文件断点续传

DataPipeline正式加入中国信通院数据库应用创新实验室!

DataPipeline数见科技

数据库 中间件 数据融合 数据管理 信通院

给弟弟的信第24封|盲目的努力没有用

大菠萝

28天写作

全链路压测系列(一):认识全链路压测

老张

性能测试 全链路压测

重载(overload) 和重写(override) 的区别?重载的方法能否根据返回类型进行区分?

海拥(haiyong.site)

28天写作 12月日更

MySQL的死锁系列- 锁的类型以及加锁原理

程序员历小冰

MySQL 死锁 28天写作 12月日更

全链路压测系列(二):方案调研和项目立项

老张

性能测试 全链路压测

在线JSON转Go Struct工具

入门小站

工具

[架构实战营]模块4作业

Vincent

「架构实战营」

设计千万级学生管理系统的考试试卷存储方案

ren

#架构实战营

性能基础之理解Linux系统平均负载和CPU使用率

zuozewei

Linux 性能测试 计算机原理 12月日更

什么是 DID 身份,为什么需要 DID

Rayjun

区块链 did

Reactor模式和Java NIO

Java·课代表

Java reactor 设计模式 网络编程 nio

语音信号的时域分析

轻口味

28天写作 12月日更

发射、加速与着陆:一群科学家的奥林帕斯探索之旅

脑极体

Trino应用Iceberg Catalog写入数据原理分析

漫长的白日梦

数据湖 iceberg trino

再见 Typora!这个开源的 Markdown 编辑器爱了!

JackTian

程序员 写作 Typora 编辑器 markdown编辑器

微服务划分的思考

无心水

微服务 微服务架构 SpringCloud 注册中心 微服务划分

关于分布式系统共识的思考

yuexin_tech

分布式

学生管理系统详细架构设计

swallowluo

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

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