从NullObject谈C#6.0改进(1)

作者:   出处:互联网   2015-06-24 14:08:50   阅读:2

本文来聊一聊们经常会做的空值检查问题,从一个简单的空值检查Any Where,到设计模式的NullObjectPattern,再到C#6.0“可能”会提供的语法,让们体验一次语言开发上的“持续改进”,Let’s go~

 

AD:
 

 

从NullObject谈C#6.0改进

 

什么是空引用异常

 

作为一个敲过代码的码农来说,似乎没有谁没有遇到过NullReferenceException这 个问题,有些时候当方法内部调用一个属性、方法(委托)时,们控制这些属性在 外部 的表现(当然某些情况下使用ref关键字除外),所以们要在方法 的内部去判断属性、委托方法是否为Null来避免可能的、错误使用上带来的空引用异常,这样当们知道如果对象为Null的话,们会实现符合们 预 期 的行为。

 

解决空引用异常---Check Any Where

 

这很简单,只要在需要用的地方检查一下是否为Null就可以了。是的,这非常简单,语义也很清晰,但是当你要重复检查一个对象实体10000万次时,代码中将存在10000个如下代码段:

 

 

 

public void Check() { if (Person.AlivePerson() != null) { Person.AlivePerson().KeepAlive = true; } } 

 

 

 

你能容忍这样的行为吗?

 

If(OK)

 

Continue;

 

Else

 

Close;

 

应用NullObject设计模式

 

NullObjectPattern出自forth by Gamma(设计模式4人组),核心内容是:提供一个给定对象的空值代理,空值代理中提供不做任何事情的方法实现。

 

接下来让们看看维基百科上的C#实现:

 

 

 

// compile as Console Application, requires C# 3.0 or higher using System; using System.Linq; namespace MyExtensionWithExample { public static class StringExtensions { public static int SafeGetLength(this string valueOrNull) { return (valueOrNull ?? string.Empty).Length; } } public static class Program { // define some strings static readonly string[] strings = new [] {  Mr X. ,  Katrien Duck , null,  Q  }; // write the total length of all the strings in the array public static void Main(string[] args) { var query = from text in strings select text.SafeGetLength(); // no need to do any checks here Console.WriteLine(query.Sum()); // The output will be: 18 } } } 

 

 

 

在C#语言中,们通过静态的扩展方法来实现将检查方式统一在方法内部,而不是写的到处都是,上面的例子中是在String类上实现了一个SafeGetLength扩展方法,将为所有String类型提供了一个方法,这样们在 代码整洁 上又进了一步。

 

下面们再来看一个更常用的例子---来自于StackOverFlow

 

 

 

public static class EventExtensions  {  public static void Raise T (this EventHandler T  evnt, object sender, T args)  where T : EventArgs  {  if (evnt != null)  {  evnt(sender, args);  }  }  } 

 

 

 

最后,说一个细节问题,以上代码均没有实现 线程安全 ,在大牛Eric Lippert的文章中针对线程安全有过一个更精彩的讨论,请戳这里。

 

改进后的代码时在方法内部增加了一个临时变量,作为方法内部的拷贝,实现线程安全,如果有疑问请参考《C#堆vs栈》中对方法内部变量在堆栈上的表现一章。

 

 

 

public class SomeClass { public event EventHandler EventArgs  MyEvent; private void DoSomething() { var tmp = MyEvent; tmp.Raise(this, EventArgs.Empty); } } 

 

Copyright© 2006-2015 ComponentCN.com all rights reserved.重庆磐岩科技有限公司(控件中国网) 版权所有 渝ICP备12000264号 法律顾问:元炳律师事务所
客服软件
live chat