ASP.NET网页编程之[你必需晓得的.NET]第二十一回:熟悉周全的null仓酷云
今天去面试,被问到C#中的new关键字,看了那么多的书对new关键字还是有一定认识,回来又把new复习了一遍,发现了许多以前还不知道的细节。系列文章目次索引:《你必需晓得的.NET》说在,开篇之前
null、nullable、??运算符、nullobject形式,这些闪亮的观点在你长远晃悠,我们有来由信任“存期近公道”,现实上,null不但公道,并且主要。本文,从null的基础认知入手下手,逐层懂得可空范例、??运算符和nullobject形式,在循序之旅中懂得纷歧样的null。
你必需晓得的.NET,持续全新体验,分享更多色采。
1从甚么是null入手下手?
null,一个值得尊崇的数据标识。
一样平常说来,null暗示空范例,也就是暗示甚么都没有,可是“甚么都没有”其实不意味“甚么都不是”。实践上,null是云云的主要,乃至于在JavaScript中,Null范例就作为5种基础的原始范例之一,与Undefined、Boolean、Number和String不相上下。这类主要性一样体现在.NET中,可是必定要廓清的是,null其实不同等于0,"",string.Empty这些一般意义上的“零”值观点。相反,null具有实其实在的意义,这个意义就是用于标识变量援用的一种形态,这类形态暗示没有援用任何对象实例,也就是暗示“甚么都没有”,既不是Object实例,也不是User实例,而是一个空援用罢了。
在上述让我都拗口抓狂的表述中,实在中央头脑就是廓清一个关于null意义的有力诉说,而在.NET中null又有甚么实践的意义呢?
在.NET中,null暗示一个对象援用是有效的。作为援用范例变量的默许值,null是针对指针(援用)而言的,它是援用范例变量的专属观点,暗示一个援用范例变量声明但未初始化的形态,比方:
objectobj=null;此时obj仅仅是一个保留在线程栈上的援用指针,不代表任何意义,obj未指向任何无效实例,而被默许初始化为null。
objectobj和objectobj=null的区分?
那末,objectobj和objectobj=null有实践的区分吗?谜底是:有。次要表现在编译器的反省上。默许情形下,创立一个援用范例变量时,CLR行将其初始化为null,暗示不指向任何无效实例,以是实质上两者暗示了不异的意义,可是有有所区分:
//Copyright:www.anytao.com//Author:Anytao,http://www.anytao.com//Release:2008/07/311.0//编译器检测毛病:利用未赋值变量obj//objectobj;//编译器了解为实行了初始化操纵,以是不激发编译时毛病objectobj=null;//Copyright:www.anytao.com0//Copyright:www.anytao.com1//Copyright:www.anytao.com2//Copyright:www.anytao.com3//Copyright:www.anytao.com4//Copyright:www.anytao.com5注:当我把这个成绩抛给几个伴侣时,对此的设法都未构成一致的共鸣,几位同道各有各的了解,也各有个的事理。固然,我也稳重的对此举行了一番切磋和剖析,可是并未构成完整100%断定性的谜底。不外,在了解上我更偏向于本人的剖析和判别,以是在给出上述结论的基本上,也将这个小小的思索留给人人来切磋,好的思索和剖析别忘了留给人人。现实上,将
//Copyright:www.anytao.com6//Copyright:www.anytao.com2//Copyright:www.anytao.com8//Copyright:www.anytao.com9//Copyright:www.anytao.com5反编译为IL时,两者在IL层仍是存在必定的不同:
//Author:Anytao,http://www.anytao.com1//Author:Anytao,http://www.anytao.com2//Author:Anytao,http://www.anytao.com3//Author:Anytao,http://www.anytao.com4//Author:Anytao,http://www.anytao.com5//Author:Anytao,http://www.anytao.com6//Author:Anytao,http://www.anytao.com7//Author:Anytao,http://www.anytao.com8//Author:Anytao,http://www.anytao.com9//Release:2008/07/311.00//Release:2008/07/311.01//Release:2008/07/311.02前者没有产生任何附加操纵;尔后者经由过程ldnull指令促进一个空援用给evaluationstack,而stloc则将空援用保留。
回到划定规矩
在.NET中,对null有以下的基础划定规矩和使用:
[*]null为援用范例变量的默许值,为援用范例的观点范围。
[*]null不同等于0,"",string.Empty。
[*]援用is或as形式对范例举行判别或转换时,必要做进一步的null判别。
<br>快速参考
[*]关于is和as形式,能够参考《你必需晓得的.NET》7.5节“恩仇情仇:is和as”
[*]第一回:恩仇情仇:is和as
[*]判别一个变量是不是为null,能够使用==或!=操纵符来完成。
[*]对任何值为nul的l变量操纵,城市抛出NullReferenceException非常。
2Nullable<T>(可空范例)
一向以来,null都是援用范例的特有产品,对值范例举行null操纵将在编译器抛堕落误提醒,比方:
//Release:2008/07/311.03//Release:2008/07/311.04//Release:2008/07/311.05//Copyright:www.anytao.com2//Release:2008/07/311.07//Release:2008/07/311.08正如示例中所示,良多情形下作为开辟职员,我们更但愿可以以一致的体例来处置,同时也但愿可以办理实践营业需求中关于“值”也能够为“空”这一实践情形的映照。因而,自.NET2.0以来,这一特权被新的System.Nullable<T>(即,可空值范例)的出生而冲破,排除上述诟病能够很简单以上面的体例被完成:
//Release:2008/07/311.090//Release:2008/07/311.05//Copyright:www.anytao.com2//Release:2008/07/311.07//Release:2008/07/311.08你大概很奇异上述示例中并没有任何Nullable的影子,实践上这是C#的一个语法糖,以下代码在实质上是完整等效的:
56明显,我们更中意以第一种简便而文雅的体例来完成我们的代码,可是在实质上Nullable<T>和T?他们是一丘之貉。
可空范例的巨大意义在于,经由过程Nullable<T>范例,.NET为值范例增加“可空性”,比方Nullable<Boolean>的值就包含了true、false和null,而Nullable<Int32>则暗示值便可觉得整形也能够为null。同时,可空范例完成了一致的体例来处置值范例和援用范例的“空”值成绩,比方值范例也能够享有在运转时以NullReferenceException非常来处置。
别的,可空范例是内置于CLR的,以是它并不是c#的独门特技,VB.NET中一样存在不异的观点。
Nullable的实质(IL)
那末我们怎样来熟悉Nullable的实质呢?当你声明一个:
7时,究竟产生了甚么样的历程呢?我们起首来懂得一下Nullable在.NET中的界说:
8//Copyright:www.anytao.com2//编译器检测毛病:利用未赋值变量obj0//编译器检测毛病:利用未赋值变量obj1//编译器检测毛病:利用未赋值变量obj2//编译器检测毛病:利用未赋值变量obj3//编译器检测毛病:利用未赋值变量obj4//编译器检测毛病:利用未赋值变量obj5//编译器检测毛病:利用未赋值变量obj6//编译器检测毛病:利用未赋值变量obj7//编译器检测毛病:利用未赋值变量obj8//编译器检测毛病:利用未赋值变量obj9//objectobj;0//objectobj;1//Copyright:www.anytao.com5依据上述界说可知,Nullable实质上还是一个struct为值范例,实在例对象仍旧分派在线程栈上。个中的value属性封装了详细的值范例,Nullable<T>举行初始化时,将值范例赋给value,能够从其机关函数获知:
//objectobj;3//Copyright:www.anytao.com2//objectobj;5//objectobj;6//Copyright:www.anytao.com5同时Nullable<T>完成响应的Equals、ToString、GetHashCode办法,和显式和隐式对原始值范例与可空范例的转换。因而,在实质上Nullable能够看着是预界说的struct范例,创立一个Nullable<T>范例的IL暗示能够十分明晰的供应例证,比方创立一个值为int型可空范例历程,其IL能够暗示为:
//objectobj;8//Copyright:www.anytao.com2//Author:Anytao,http://www.anytao.com31//Author:Anytao,http://www.anytao.com53456789//Copyright:www.anytao.com5关于可空范例,一样必要需要的小结:
[*]可空范例暗示值为null的值范例。
[*]不同意利用嵌套的可空范例,比方Nullable<Nullable<T>>。
[*]Nullable<T>和T?是等效的。
[*]对可空范例实行GetType办法,将前往范例T,而不是Nullable<T>。
[*]c#同意在可空范例上实行转换和转型,比方:
//编译器了解为实行了初始化操纵,以是不激发编译时毛病1//编译器了解为实行了初始化操纵,以是不激发编译时毛病2//编译器了解为实行了初始化操纵,以是不激发编译时毛病3
[*]同时为了更好的将可空范例于原本的范例体系举行兼容,CLR供应了对可空范例装箱和拆箱的撑持。
3??运算符
在实践的程序开辟中,为了无效制止产生非常情形,举行null判断是常常产生的事变,比方关于恣意对象实行ToString()操纵,都应当举行需要的null反省,以避免产生不用要的非常提醒,我们经常是如许完成的:
//编译器了解为实行了初始化操纵,以是不激发编译时毛病4//编译器了解为实行了初始化操纵,以是不激发编译时毛病6//编译器了解为实行了初始化操纵,以是不激发编译时毛病7//编译器了解为实行了初始化操纵,以是不激发编译时毛病8//编译器了解为实行了初始化操纵,以是不激发编译时毛病9//Copyright:www.anytao.com5objectobj=null;2但是这类完成其实是使人作呕,满篇的if语句老是让人看着满身不适,那末另有更好的完成体例吗,我们能够实验(?:)三元运算符:
//编译器了解为实行了初始化操纵,以是不激发编译时毛病4objectobj=null;4objectobj=null;2上述obj能够代表恣意的自界说范例对象,你能够经由过程覆写ToString办法来输入你想要输入的了局,由于上述完成是云云的频仍,以是.NET3.0中供应了新的操纵运算符来简化null值的判别历程,这就是:??运算符。上述历程能够以加倍震动的代码体现为:
//Copyright:www.anytao.com//Author:Anytao,http://www.anytao.com//Release:2008/07/311.0objectobj=null;//Copyright:www.anytao.com01objectobj=null;2那末??运算符的详细感化是甚么呢?
??运算符,又称为null-coalescingoperator,假如左边操纵数为null,则前往右边操纵数的值,假如不为null则前往左边操纵数的值。它既能够使用于可空范例,有能够使用于援用范例。
4NulllObject形式
形式之于计划,正如秘籍之于工夫。正如我们前文所述,null在程序计划中具有无足轻重的感化,因而怎样更文雅的处置“对象为空”这一广泛成绩,大家们提出了NullObjectPattern观点,也就是我们常说的NullObject形式。比方Bob年夜叔在《急迅软件开辟--准绳、形式、理论》一书,MartinFowler在《Refactoring:ImprovingtheDesignofExistingCode》一书,都曾就NullObject形式睁开具体的会商,可见23中形式以外仍是有良多计划精华,大概称为形式有碍典范。可是仍旧值得我们挖据、探究和发明。
上面就一气呵成,在null熟悉的基本上,对nullobject形式举行一点切磋,研讨nullobject办理的成绩,并提出通用的nullobject使用体例。
办理甚么成绩?
复杂来讲,nullobject形式就是为对象供应一个指定的范例,来取代对象为空的情形。说白了就是办理对象为空的情形,供应对象“甚么也不做”的举动,这类体例看似无聊,但倒是很伶俐的办理之道。举例来讲,一个User范例对象user必要在体系中举行操纵,那末典范的操纵体例是:
//Copyright:www.anytao.com03//Copyright:www.anytao.com2//Copyright:www.anytao.com05//Release:2008/07/311.08这类相似的操纵,会遍及于你的体系代码,有数的if判别让文雅阔别了你的代码,假如粗心健忘null判别,那末只要无情的非常奉养了。因而,Nullobject形式就应运而生了,对User类完成不异功效的NullUser范例,就能够无效的制止烦琐的if和不用要的掉误:
//Copyright:www.anytao.com//Author:Anytao,http://www.anytao.com//Release:2008/07/311.0//Copyright:www.anytao.com11//Copyright:www.anytao.com2//Copyright:www.anytao.com13//Copyright:www.anytao.com2//Copyright:www.anytao.com15//Release:2008/07/311.08//Copyright:www.anytao.com18//Copyright:www.anytao.com20//编译器了解为实行了初始化操纵,以是不激发编译时毛病8//Copyright:www.anytao.com22//Copyright:www.anytao.com5//Release:2008/07/311.08IsNull属性用于供应一致判断null体例,假如对象为NullUser实例,那末IsNull必定是true的。
那末,两者的不同表现在哪儿呢?实在次要的思绪就是将nullvalue转换为nullobject,把对user==null如许的判别,转换为user.IsNull固然只要一字之差,可是实质上是完整两回事儿。经由过程nullobject形式,能够确保前往无效的对象,而不是没有任何意义的null值。同时,“在实行办法时前往nullobject而不是null值,能够制止NullReferenceExecption非常的产生。”,这是来自ScottDorman的声响。
通用的nullobject计划
上面,我们完成一种较为通用的nullobject形式计划,并将实在现为具有.NET特征的nullobject,以是我们接纳完成.NET中INullable接口的体例来完成,INullable接口是一个包含了IsNull属性的接口,其界说为:
//Copyright:www.anytao.com25//Copyright:www.anytao.com2//Copyright:www.anytao.com27//Copyright:www.anytao.com28//Copyright:www.anytao.com5仍旧以User类为例,完成的计划能够表达为:
<br>
图中仅仅枚举了复杂的几个办法或属性,旨在到达申明思绪的目标,个中User的界说为:
//Copyright:www.anytao.com//Author:Anytao,http://www.anytao.com//Release:2008/07/311.0//Copyright:www.anytao.com34//Copyright:www.anytao.com2//Copyright:www.anytao.com13//Copyright:www.anytao.com2//Copyright:www.anytao.com38//Release:2008/07/311.08//Copyright:www.anytao.com41//编译器了解为实行了初始化操纵,以是不激发编译时毛病8//Copyright:www.anytao.com43//Copyright:www.anytao.com5//Copyright:www.anytao.com46//Copyright:www.anytao.com2//Copyright:www.anytao.com48//Release:2008/07/311.08//Copyright:www.anytao.com5而对应的NullUser,其界说为:
//Copyright:www.anytao.com//Author:Anytao,http://www.anytao.com//Release:2008/07/311.0//Copyright:www.anytao.com11//Copyright:www.anytao.com2//Copyright:www.anytao.com13//Copyright:www.anytao.com2//Copyright:www.anytao.com15//Release:2008/07/311.08//Copyright:www.anytao.com18//Copyright:www.anytao.com20//编译器了解为实行了初始化操纵,以是不激发编译时毛病8//Copyright:www.anytao.com22//Copyright:www.anytao.com5//Release:2008/07/311.08同时经由过程UserManager类来完成对User的操纵和办理,你很简单思索经由过程联系关系体例,将IUser作为UserManger的属性来完成,基于对nullobject的引进,完成的体例能够为:
//Copyright:www.anytao.com//Author:Anytao,http://www.anytao.com//Release:2008/07/311.0//Copyright:www.anytao.com73//Copyright:www.anytao.com2//Copyright:www.anytao.com75//Copyright:www.anytao.com77//Copyright:www.anytao.com2//Copyright:www.anytao.com79//Copyright:www.anytao.com80//编译器了解为实行了初始化操纵,以是不激发编译时毛病8//Copyright:www.anytao.com82//Copyright:www.anytao.com5//Release:2008/07/311.08//Copyright:www.anytao.com5固然无效的测试是需要的:
//Copyright:www.anytao.com86//Copyright:www.anytao.com2//Copyright:www.anytao.com88//Copyright:www.anytao.com89//Copyright:www.anytao.com90//Copyright:www.anytao.com91//Copyright:www.anytao.com92//Copyright:www.anytao.com94//Copyright:www.anytao.com2//Copyright:www.anytao.com96//Release:2008/07/311.08//Copyright:www.anytao.com5经由过程强迫将User属性完成为null,在挪用Login时仍旧可以包管体系的不乱性,无效制止对null的判断操纵,这最少可让我们的体系少了良多不用要的判断代码。
具体的代码能够经由过程本文最初的下载空间举行下载。实践上,能够经由过程引进FacotryMethod形式来构建关于User和NullUser的创立事情,如许就能够完整打消使用if举行判别的僵化,不外那是别的一项事情而已。
固然,这只是nullobject的一种完成计划,在此对《Refactoring》一书的示例举行改进,完成更具有.NET特征的nullobject完成,你也能够请NullUser承继Use并增加响应的IsNull判断属性来完成。
借力c#3.0的Nullobject
在C#3.0中,ExtensionMethod(扩大办法)关于成绩LINQ居功至伟,可是ExtensionMethod的奇妙远不是止于LINQ。在实践的计划中,天真而奇妙的使用,一样能够给你的计划带来意想不到的震动,以上述User为例我们使用ExtensionMethod来取巧完成更简便IsNull判断,取代完成INullable接口的办法而接纳更复杂的完成体例。从头机关一个完成不异功效的扩大办法,比方:
//Copyright:www.anytao.com//Author:Anytao,http://www.anytao.com//Release:2008/07/311.0//Author:Anytao,http://www.anytao.com03//Copyright:www.anytao.com2//Author:Anytao,http://www.anytao.com05//Copyright:www.anytao.com2//Author:Anytao,http://www.anytao.com07//Release:2008/07/311.08//Copyright:www.anytao.com5固然,这只是一个复杂的思绪,仅仅将对nullvalue的判别转换为nullobject的判别角度来看,扩大办法带来了更无效的、更简便的体现力。
nullobject形式的小结
[*]无效办理对象为空的情形,为值为null供应牢靠包管。
[*]包管可以前往无效的默许值,比方在一个IList<User>userList中,可以包管任何情形下都有无效值前往,能够包管对userList操纵的无效性,比方:
//Copyright:www.anytao.com//Author:Anytao,http://www.anytao.com//Release:2008/07/311.0//Author:Anytao,http://www.anytao.com14//Copyright:www.anytao.com2//Author:Anytao,http://www.anytao.com16//Author:Anytao,http://www.anytao.com17//编译器了解为实行了初始化操纵,以是不激发编译时毛病8//Author:Anytao,http://www.anytao.com19//Copyright:www.anytao.com5//Release:2008/07/311.08
[*]供应一致判断的IsNull属性。能够经由过程完成INullable接口,也能够经由过程ExtensionMethod完成IsNull判断办法。
[*]nullobject要坚持原object的一切成员的稳定性,以是我们经常将实在现为Sigleton形式。
[*]ScottDoman说“在实行办法时前往nullobject而不是null值,能够制止NullReferenceExecption非常的产生”,这完整是对的。
5结论
固然形色仓促,可是经由过程本文你能够基础懂得关于null这个话题的各个方面,聚积到一同就是对一个观点明晰的掌控和切磋。手艺的魅力,也许也恰是云云罢了吧,色采斑斓的天下里,即使是“甚么都没有”的null,在我看来仍然有良多良多。。。值得探究、思索和分享。
另有更多的null,比方LINQ中的null,SQL中的null,仍旧能够举行切磋,我们将这类思索持续,所劳绩的果实就越多。
参考文献
(Book)MartinFowler,Refactoring:ImprovingtheDesignofExistingCode
(cnblogs)zhuweisky,利用NullObject计划形式
(blogs)ScottDorman,NullObjectpattern
来自:http://www.ckuyun.com/anytao/archive/2008/07/31/must_net_21.html
我感觉可以顶到50楼,出乎意料的是大家居然纷纷写出自己的博文,还被编辑做成了专题,置于首页头条。 ASP.Net和ASP的最大区别在于编程思维的转换,而不仅仅在于功能的增强。ASP使用VBS/JS这样的脚本语言混合html来编程,而那些脚本语言属于弱类型、面向结构的编程语言,而非面向对象。 但是目前在CGI中使用的最为广泛的是Perl语言。所以,狭义上所指的CGI程序一般都是指Perl程序,一般CGI程序的后缀都是.pl或者.cgi。 由于JSP/Servlet都是基于Java的,所以它们也有Java语言的最大优点——平台无关性,也就是所谓的“一次编写,随处运行(WORA–WriteOnce,RunAnywhere)”。除了这个优点,JSP/Servlet的效率以及安全性也是相当惊人的。 同时也感谢博客园给我们这个平台,也感谢博客园的编辑们做成专题引来这么多高人指点。 业务逻辑代码都不必做任何改动;继承性和多态性使得代码的可重用性大大提高,你可以通过继承已有的对象最大限度保护你以前的投资。并且C#和C++、Java一样提供了完善的调试/纠错体系。 现在的ASP.net分为两个版本:1.1和2.0Asp.net1.1用VS2003(visualstudio2003)编程。Asp.net2.0用VS2005(visualstudio2005)编程。现在一般开发用的是VS2003。 asp.net最主要特性包括:◆编程代码更简洁◆网站可实现的功能更强大◆运行效率高◆节省服务器的动作资源 asp.net最主要特性包括:◆编程代码更简洁◆网站可实现的功能更强大◆运行效率高◆节省服务器的动作资源 ASP(ActiveServerPages)是Microsfot公司1996年11月推出的WEB应用程序开发技术,它既不是一种程序语言,也不是一种开发工具,而是一种技术框架,不须使用微软的产品就能编写它的代码。 ASP.net1.1和2.0在程序上的语法也有很大不同,现在2.0属于新出来的,不知道半年后会不会有3.0(说笑一下)。Windows2003系统自动支持ASP和ASP.net环境,不用安装任何程序。Asp.net属于编译语言。ASP的最大不同(ASP属于解释语言)。
页:
[1]