什么是NullReferenceException作为一个敲过代码的codeer,似乎没有人没有遇到过NullReferenceException的问题。有时当一个方法调用一个属性或方法(delegate)时,我们控制这些属性的“外在”表现时(某些情况下ref关键字除外),我们需要在方法内部判断属性和delegate方法是否为Null来避免可能和错误地使用upperband,这样当我们知道如果对象为Null时,我们将实现符合我们“期望”的行为。解决空引用异常---CheckAnyWhere这个很简单,我只需要在需要使用的地方检查是否为Null即可。是的,这很简单,语义也很清楚,但是当你想要重复检查一个对象实体1亿次时,你的代码将有10,000个这样的代码段:publicvoidCheck(){if(Person.AlivePerson()!=null){Person.AlivePerson().KeepAlive=true;}}你能容忍这样的行为吗?如果(确定)继续;否则关闭;应用NullObject设计模式NullObjectPattern由Gamma提出(一组4个设计模式),核心内容是:为给定的对象提供一个空值代理,而空值代理提供一个什么都不做的代理方法实现。接下来看看维基百科上的C#实现://compileasConsoleApplication,requiresC#3.0orhigherusingSystem;usingSystem.Linq;namespaceMyExtensionWithExample{publicstaticclassStringExtensions{publicstaticintSafeGetLength(thisstringvalueOrNull){return(valueOrNull??string.Empty).Length;}}publicstatic{//definesomestringsstaticreadonlystring[]strings=new[]{"MrX.","KatrienDuck",null,"Q"};//writethetotallengthofallthestringsinthearraypublicstaticvoidMain(string[]args){varquery=fromtextinstringsselecttext.SafeGetLength();//不需要做任何检查。WriteLine(query.Sum());//Theoutputwillbe:18}}}在C#语言中,我们使用静态扩展方法将校验方法统一在方法内部,而不是到处写。在上面的例子中就是在String类上实现了一个SafeGetLength扩展方法,它会为所有String类型提供一个方法,这样我们在“代码整洁度”上又进了一步。让我们看一个更常用的例子---来自StackOverFlow}}}***再说一个细节。以上代码均未实现“线程安全”。DanielEricLippert的文章中有关于线程安全的更精彩的讨论,请点击这里。改进后的代码在方法内部添加了一个临时变量作为方法内部的副本,以实现线程安全。有问题可以参考我的《C#堆vs栈》中方法内部变量在栈上的表现章节。publicclassSomeClass{publiceventEventHandlerMyEvent;privatevoidDoSomething(){vartmp=MyEvent;tmp.Raise(this,EventArgs.Empty);}}#p#More"trendy"way-C#6.0语法来自MSDN杂志的MarkMichaelis(《C#本质论》作者)向我们介绍了C#6.0可能给语言带来的新改进,包括对“Null条件运算符”的改进。 C#6.0更多参考: 第一部分:https://msdn.microsoft.com/zh-cn/magazine/dn683793.aspx 第二部分:https://msdn.microsoft.com/zh-cn/magazine/dn802602.aspx 即使是.NET开发新手也可能对NullReferenceException非常熟悉。一个例外是几乎总是会指出错误,因为开发人员在调用对象的(null)成员之前没有执行足够的null检查。请看下面的例子:publicstaticstringTruncate(stringvalue,intlength){stringresult=value;if(value!=null)//Skipemptystringcheckforelucidation{result=value.Substring(0,Math.Min(value.Length,length));}returnresult;}如果不进行null检查,此方法将抛出NullReferenceException。虽然这很简单,但检查字符串参数是否为null的过程有点乏味。一般来说,考虑到比较的频率,这种繁琐的方法可能没有必要。C#6.0包含一个新的空条件运算符,可帮助您更轻松地编写这些检查:publicstaticstringTruncate(stringvalue,intlength){returnvalue?.Substring(0,Math.Min(value.Length,length));}[TestMethod]publicvoidTruncate_WithNull_ReturnsNull(){Assert.AreEqual(null,Truncate(null,42));}如Truncate_WithNull_ReturnsNull方法所示,如果对象的值实际为null,则null条件运算符将返回null。这就引出了一个问题,当调用链中出现null条件运算符时会发生什么?如以下示例所示:>(42,AdjustWidth("InigoMontoya",42).Length);}虽然Substring是用null条件运算符调用的,并且nullvalue?.Substring似乎返回null,但语言的行为与您想象的一样。这简化了对PadRight的调用并立即返回null,避免了会导致NullReferenceException的编程错误。这个概念称为“空传播”。空条件运算符在调用目标方法和调用链中的所有其他方法之前根据条件执行空检查。这可能会产生令人惊讶的结果,例如,在text?.Length.GetType语句中。如果null条件运算符在调用目标为null时返回null,那么最终将在返回值类型的成员上调用什么数据类型(假设值类型不能为null)?例如,从value?.Length返回的数据类型不能只是int。答案当然是:可空类型(int?)。事实上,试图将结果赋值给一个int会给出一个编译错误:intlength=text?.Length;//编译错误:无法隐式转换类型'int?'to'int'Null条件有两种语法形式。首先,问号位于点运算符(?.)之前。第二,将问号与索引运算符结合起来。例如,给定一个集合(而不是在索引到集合之前显式检查null),您可以使用null条件运算符来执行此操作:publicstaticIEnumerableGetValueTypeItems(IListcollection,paramsint[]indexes)whereT:struct{foreach(intindexinindexes){T?item=collection?[index];if(item!=null)yieldreturn(T)item;}} 本示例使用运算符?[…]一个null-的条件索引形式,导致仅当集合不为null时才对集合进行索引。使用这种形式的null条件运算符,T?item=collection?[index]语句在行为上等同于:T?项目=(集合!=空)?集合[索引]:空。请注意,null条件运算符Items仅被检索,而不是被赋值。如果给定一个空集合,这意味着什么?注意使用?[…]作为引用类型时隐含的歧义。由于引用类型可以为null,因此?[…]运算符的null结果对于集合是否为null或元素本身实际上是否为null是不明确的。null条件运算符的一个非常有用的应用程序解决了自C#1.0以来就存在的C#功能,即在调用委托之前检查null。让我们看一下图中显示的C#2.0代码。 图1调用delegate前检查是否为Null=null){_Temperature=value;//调用subscriberslocalOnChanged(this,value);}}}} 通过使用null条件运算符,整个集合实现过程可以简化为:OnTemperatureChanged?.Invoke(this,value) 现在您可以简单地调用带有null条件运算符前缀的Invoke,无需将委托实例分配给局部变量以确保线程安全,甚至无需显式在调用委托之前检查空值。C#开发人员很想知道这在过去四个版本中是否有所改进。答案是最终会有所改进。仅此功能就可以改变调用委托的方式。空条件运算符得到普及的另一种常见模式是与合并运算符结合使用。您可以像这样编写项目计数算法,而不是在调用Length之前对linesOfCode进行空检查:ListlinesOfCode=ParseSourceCodeFile("Program.cs");返回linesOfCode?.Count??0;在这种情况下,任何空集合(没有项目)和空集合都被规范化以返回相同的数量。总之,空条件运算符将执行以下操作: 1。如果操作数为空则返回null 2.如果操作数为空则简化调用链中的其他调用3.如果目标成员返回值类型,则返回可空类型(System.Nullable)。 4。支持线程安全的委托调用 5。可以作为成员运算符(?.)和索引运算符(?[…])示例代码下载参考http://stackoverflow.com/questions/13629051/net-event-raising-and-nullobject-pattern---Thread-安全扩展机制https://msdn.microsoft.com/zh-cn/magazine/dn802602.aspx---C#6.0空条件操作符号http://en.wikipedia.org/wiki/Null_Object_pattern---说明维基百科上的NullObjectPattern作者:StephenCui来源:http://www.cnblogs.com/cuiyansong