QCon北京「鸿蒙专场」火热来袭!即刻报名,与创新同行~ 了解详情
写点什么

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

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

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

关注

评论

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

区块链:在发展的同时,准备好你的产品。

石云升

区块链 DCEP 创新

Java NIO 是 NIO么?

soolaugust

Java io nio

Linux 平均负载高了怎么办?

小林coding

Linux 问题处理 linux命令

SpringCloud(Netflix)-技术专题-Ribbon的基本使用

码界西柚

Java 技术 SpringCloud

高效程序员的45个习惯:敏捷开发修炼之道(2)

石云升

读书笔记 敏捷开发 对事不对人 欲速则不达

经济优势再显,江苏如何通过职教打造人才高地?

InfoQ_967a83c6d0d7

C++ static 与 const 的认识

小林coding

c++ 编程 static关键字

C++ 自增、自减运算符的重载和性能分析

小林coding

c++ 编程 运算符

职教黄金时代,河南如何继续“乘风破浪”?

InfoQ_967a83c6d0d7

超超超全递归技巧讲解,这次带你拿下递归

多选参数

数据结构 算法 递归 数据结构与算法

C++ 模板常见特性(函数模板、类模板)

小林coding

c++ 编程 模板方法

白鹭引擎助力《迷你世界》研发团队开发3D小游戏版

DT极客

微服务-技术专题-初步介绍服务发现

码界西柚

Java 技术 微服务

排序算法一(冒泡排序、选择排序、插入排序)

xcbeyond

Java 算法 冒泡排序 选择排序 插入排序

SpreadJS 纯前端表格控件应用案例:铭天预算执行系统

葡萄城技术团队

SpreadJS 预算执行系统

C++ 赋值运算符‘=‘的重载(浅拷贝、深拷贝)

小林coding

c++ 编程 浅拷贝和深拷贝

Go语言专家测试,80%的人第一题就挂了!

博文视点Broadview

云原生 评测 Go 语言

央行发行的数字货币会带来哪些变化?

石云升

区块链 数字货币 DECP

C++ 手把手教你实现可变长的数组

小林coding

c++ 编程 数组

Java-技术专题-final关键字

码界西柚

云计算的可信新边界:边缘计算与协同未来——【两万五千字长文】

华为云开发者联盟

云计算 云原生 5G 边缘计算 云服务

C++ this指针的理解和作用

小林coding

c c++ 指针

C++ 运算符重载的基本概念

小林coding

c++ 编程

最佳实践:使用阿里云CDN加速OSS访问

阿里云Edge Plus

CDN

C++ 流插入和流提取运算符的重载

小林coding

c++ 编程

Volcano:带你体验容器与批量计算的碰撞的火花

华为云开发者联盟

Kubernetes 容器 分布式 Volcano 批量计算

使用 Golang 和 HTML5 开发一个 MacOS App

郭旭东

macos Go 语言

2. 整体把握 CocoaPods 核心组件

Edmond

ruby ios swift CocoaPods 包管理工具

大数据技术发展(一):大数据技术的起源

cristal

Java 大数据 hadoop

C++ 一篇搞懂多态的实现原理

小林coding

c++ 编程 封装、继承、多态

C++ 一篇搞懂继承的常见特性

小林coding

c++ 编程 继承

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