2025上半年,最新 AI实践都在这!20+ 应用案例,任听一场议题就值回票价 了解详情
写点什么

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

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

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

关注

评论

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

探究Presto SQL引擎(3)-代码生成

vivo互联网技术

sql presto antlr4

性能优化手记下篇之【计费】

鲸品堂

性能优化 运维

AssertJ 的异常(Exception )断言

HoneyMoose

Web Service进阶(五)SOAPBinding方式讲解

No Silver Bullet

6月月更 SOAPBinding

GIT 小白的指令合集

甜甜的白桃

git 版本管理 6月月更

微软成为规模化敏捷组织的16个关键因素

ShineScrum

敏捷 谷歌 规模化敏捷

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

呆呆敲代码的小Y

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

愚公搬代码

6月月更

软件设计本质

GalaxyCreater

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

【Python技能树共建】字符串方法

梦想橡皮擦

6月月更

spring4.1.8初始化源码学习三部曲之一:AbstractApplicationContext构造方法

程序员欣宸

Java spring 6月月更

springboot,vue,es,activiti数字知识库管理系统

金陵老街

Vue springboot ES Activiti 知识库

WordPress 常规设置

海拥(haiyong.site)

WordPress 6月月更

java培训 @Autowired 的实现原理

@零度

JAVA开发

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

呆呆敲代码的小Y

PHP开发者福音,支持CRUD代码生成且前后分离的tp6+Vue3后台管理系统开源啦!

妙码生花

php typescript Vue3 thinkphp Pinia

浅谈JavaScript原型和原型链

大熊G

JavaScript 前端 6月月更

如何使用物联网低代码平台进行模型管理?

AIRIOT

物联网 低代码开发

建木持续集成平台v2.4.1发布

Jianmu

DevOps CI/CD 开源项目 gitops 自动化运维

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

呆呆敲代码的小Y

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

呆呆敲代码的小Y

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

呆呆敲代码的小Y

Fabric.js 精简输出的JSON🎫

德育处主任

FabricJS 6月月更

fomo3d区块链分红游戏系统开发(案例演示)

开发微hkkf5566

重点亦难点?三个案例看数据分类分级如何有效有序进行

美创科技

数据分类 数据安全

7 个 Flutter 开源项目,让你成为更好的 Flutter 开发者

坚果

6月月更

C#入门系列(七) -- 循环语句

陈言必行

C# 6月月更

Linux驱动开发_视频广告机开发、Linux进程编程介绍

DS小龙哥

6月月更

SAP 云平台 ABAP 编程环境的前世今生

汪子熙

Cloud 云平台 SAP abap 6月月更

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

呆呆敲代码的小Y

Junit 测试中如何对异常进行断言

HoneyMoose

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