ASP.NET网站制作之深切探察C#,VB中的相称操纵符仓酷云
有时也搞不懂应该学那种;主要看你以后去的那个公司是使用哪种了。就像王千祥的课上说的:企业应用现在主要就三层(其实也差不多就是MVC):表示层(主要使用html写的,很简单)、业务逻辑层(主要就是应用服务器的)。最后就是数据层(其实就是学习数据库)重写相称操纵符长短常简单堕落的。不但由于相称操纵符有很多内在,并且今朝有良多引导文档有瑕疵,乃至在MSDN网站上有些引导文档也有瑕疵。我们将分离对撑持相称操纵的援用范例和值范例给出体系的剖析,来廓清现实。为了明晰起见,这里将类称作援用范例而布局称作值范例。
一般在布局中操纵符重载比在类中成心义,以是我们先来展现在布局中的情形。类和布局的次要区分是,类必要反省空值,而在布局中你必要意想到大概存在的范例装箱。这一点将在前面申明。
类署名
布局的署名是直截了当的。你仅仅必要用System.IEquatable接口来标识该布局。请注重这个接口没有非泛型的版本,泛型的版本的脚色由基本类Object承当。
C#structPointStruct:System.IEquatableVBPublicStructurePointStructImplementsIEquatable(OfPointStruct)类的署名实质上和布局署名是一样的。类的承继会损坏相称性,这会形成成绩。假如a是一个基类而b是一个重写了Equals办法的子类,那末a.Equals(b)会前往与b.Equals(a)分歧的前往值。前面我们经由过程关闭(sealing)的Equals办法来办理这个成绩。
C#classPointClass:System.IEquatableVBPublicClassPointClassImplementsIEquatable(OfPointClass)成员变量和属性
任何用于相称性对照的成员变量必需是不成变的。一般,这意味着类中一切的属性是只读的大概类有一个相似于数据库主键的独一标识符。
在利用任何依附哈希的工具的时分这条划定规矩都是相当主要的。如许的例子包含Hashtable、Dictionary、HashSet和KeyedCollection。这些类都利用哈希码作查找和存储。假如对象的哈希码变更了,它会被放在毛病的槽中并且汇合不克不及再准确的事情。最多见的妨碍是不克不及找到之前放在汇合中的对象。
为了确保成员变量是不成变的,它们被标志为只读的。因为成员变量能够在机关器中设置,以是改动成员变量有点象写错名字。可是一旦初始化完成了,没无方法能够间接改动成员变量的值。
C#readonlyint_X;readonlyint_Y;publicPointStruct(intx,inty){_X=x;_Y=y;}intX{get{return_X;}}intY{get{return_Y;}}VBPrivateReadOnlym_XAsIntegerPrivateReadOnlym_YAsIntegerPublicSubNew(ByValxAsInteger,ByValyAsInteger)m_X=xm_Y=yEndSubPublicReadOnlyPropertyX()AsIntegerGetReturnm_XEndGetEndPropertyPublicReadOnlyPropertyY()AsIntegerGetReturnm_YEndGetEndProperty因为类版本的代码与下面的代码几近是不异的,且在VB中是完整不异的,以是这里不给出类版本代码。
范例平安的相称办法
我们完成的第一个办法是范例平安的相称办法,在IEquatable接口中利用。
C#publicboolEquals(PointStructother){return(this._X==other._X)&&(this._Y==other._Y);}VBPublicOverloadsFunctionEquals(ByValotherAsPointStruct)AsBoolean_ImplementsSystem.IEquatable(OfPointStruct).EqualsReturnm_X=other.m_XAndAlsom_Y=other.m_YEndFunction关于类,必要分外反省空值。依照常规,一切非空值被以为与空值不相称。
你会注重到我们没有利用隧道的C#代码来反省空值。这是因为C#和VB处置相称性的体例有一处分歧。
VisualBasic在处置援用相称和值相称上有明白的区分。前者利用Is擦作符,后者利用=操纵符。
C#缺少这类区分,对二者都利用==操纵符。因为我们会重写==操纵符,以是不想利用==,不能不转而利用一个后门。这个后门是Object.ReferenceEquals办法。
因为类老是与本人相称,以是在举行潜伏的更高贵的相称性反省之前,我们起首作这个反省。鄙人面代码中我们对照了公有成员变量,也能够利用属性来作对照。
C#publicboolEquals(PointClassother){if(Object.ReferenceEquals(other,null)){returnfalse;}if(Object.ReferenceEquals(other,this)){returntrue;}return(this._X==other._X)&&(this._Y==other._Y);}VBPublicOverloadsFunctionEquals(ByValotherAsPointClass)AsBooleanImplementsSystem.IEquatable(OfPointClass).EqualsIfotherIsNothingThenReturnFalseIfotherIsMeThenReturnTrueReturnm_X=other.m_XAndAlsom_Y=other.m_YEndFunction哈希码
下一步是发生哈希码。最复杂的办法是将一切用于相称性对照的成员变量的哈希码作异或运算。
C#publicoverrideintGetHashCode(){return_X.GetHashCode()^_Y.GetHashCode();}VBPublicOverridesFunctionGetHashCode()AsIntegerReturnm_X.GetHashCodeXorm_Y.GetHashCodeEndFunction假如你的确决意要重新写本人的哈希码,你必需确保关于一套给定的值,你老是能前往不异的哈希码。换言之,假如a即是b,那末它们的哈希码也相称。
哈希码不用是独一的,分歧的值能够有不异的哈希码。可是它们应当有一个优秀的散布。关于每个哈希码都前往42在手艺上是正当的,可是任何利用该算法的使用在功能上城市很糟。
哈希码应当以十分快的速率盘算出来。因为盘算哈希值大概成为瓶颈,以是宁肯选用一个疾速的有公道优秀散布的哈希码算法,而不选择一个慢的,庞大的有着完善的匀称散布的算法。
相称(对象)
重写基类的Equals办法是一个基本事情,该办法被Object.Equals(Object,Object)函数和其他办法挪用。
你应当注重到因为范例转换做了两次,以是大概存在一点功能成绩:一次是看它是不是无效,第二次是真实的实行它。不幸的是,在布局中是没法制止如许作的。
C#publicoverrideboolEquals(objectobj){if(objisPointStruct){returnthis.Equals((PointStruct)obj);}returnfalse;}VBPublicOverridesFunctionEquals(ByValobjAsObject)AsBooleanIfTypeOfobjIsPointStructThenReturnCType(obj,PointStruct)=MeEndFunction关于类能够只用一次范例转换。在处置步骤中,我们能够早点检测空值然后跳过对Equals(PointClass)办法的挪用。C#必需用ReferenceEquals函数来反省空值。
为了避免子类损坏相称性,我们关闭(Seal)了办法。
C#publicsealedoverrideboolEquals(objectobj){vartemp=objasPointClass;if(!Object.ReferenceEquals(temp,null)){returnthis.Equals(temp);}returnfalse;}VBPublicNotOverridableOverridesFunctionEquals(ByValobjAsObject)AsBooleanDimtemp=TryCast(obj,PointClass)IftempIsNotNothingThenReturnMe.Equals(temp)EndFunction操纵符重载
一切的困难都被霸占了,我们如今能够举行操纵符的重写了。这里和挪用范例平安的Equlas办法一样复杂。
C#publicstaticbooloperator==(PointStructpoint1PointStructpoint2){returnpoint1.Equals(point2);}publicstaticbooloperator!=(PointStructpoint1,PointStructpoint2){return!(point1==point2);}VBPublicSharedOperator=(ByValpoint1AsPointStruct,ByValpoint2AsPointStruct)AsBooleanReturnpoint1.Equals(point2)EndOperatorPublicSharedOperator(ByValpoint1AsPointStruct,ByValpoint2AsPointStruct)AsBooleanReturnNot(point1=point2)EndOperator关于类,必要反省空值。侥幸的是,Object.Equals(object,object)为你处置了这类情形。然后挪用已被重写的Object.Equals(Object)办法。
C#publicstaticbooloperator==(PointClasspoint1,PointClasspoint2){returnObject.Equals(point1,point2);}publicstaticbooloperator!=(PointClasspoint1,PointClasspoint2){return!(point1==point2);}VBPublicSharedOperator=(ByValpoint1AsPointClass,ByValpoint2AsPointClass)AsBooleanReturnObject.Equals(point1,point2)EndOperatorPublicSharedOperator(ByValpoint1AsPointClass,ByValpoint2AsPointClass)AsBooleanReturnNot(point1=point2)EndOperator功能
你会注重到每一个挪用链都有点长,特别是不相称操纵符。假如必要思索功能成绩,你能够分离在每一个办法中完成对照逻辑来进步速率。如许很简单堕落并且使得保护事情对照棘手,以是仅仅当你利用功能检测工具证实了必需如许作以后,才应当如许作。
测试
本文利用了上面的测试。它利用了列表的情势使得你能够便利的将它们翻译到你最喜好的单位测试框架中。由于相称性很简单被损坏,以是这是单位测试的主要的测试方针。
请注重测试不是周全的。你应当测试摆布值部分相称的情形,比方PointStruct(1,2)andPointStruct(1,5)。
VariableTypeValueAPointStructnewPointStruct(1,2)a2PointStructnewPointStruct(1,2)BPointStructnewPointStruct(3,4)nullValueObjectNull
ExpressionExpectedValueEqualvaluesa==a2Truea!=a2Falsea.Equals(a2)Trueobject.Equals(a,a2)TrueUnequalvalues,aonleftb==aFalseb!=aTrueb.Equals(a)Falseobject.Equals(b,a)FalseUnequalvalues,aonrighta==bFalsea!=bTruea.Equals(b)Falseobject.Equals(a,b)Falsenulls,aonlefta.Equals(nullValue)Falseobject.Equals(a,nullValue)Falsenulls,aonrightobject.Equals(nullValue,a)FalseHashcodesa.GetHashCode()==a2.GetHashCode()Truea.GetHashCode()==b.GetHashCode()Indeterminate
VariableTypeValueaPointClassnewPointClass(1,2)a2PointClassnewPointClass(1,2)bPointClassnewPointClass(3,4)nullValuePointClassNullnullValue2PointClassNull
ExpressionExpectedValueSameObjecta==aTruea!=aFalsea.Equals(a)Trueobject.Equals(a,a)TrueEqualvaluesa==a2Truea!=a2Falsea.Equals(a2)Trueobject.Equals(a,a2)TrueUnequalvalues,aonleftb==aFalseb!=aTrueb.Equals(a)Falseobject.Equals(b,a)FalseUnequalvalues,aonrighta==bFalsea!=bTruea.Equals(b)Falseobject.Equals(a,b)Falsenulls,aonlefta==nullValueFalsea!=nullValueTruea.Equals(nullValue)Falseobject.Equals(a,nullValue)Falsenulls,aonrightnullValue==aFalsenullValue!=aTrueobject.Equals(nullValue,a)FalsebothnullnullValue==nullValue2Trueobject.Equals(nullValue,nullValue2)TrueHashcodesa.GetHashCode()==a2.GetHashCode()Truea.GetHashCode()==b.GetHashCode()Indeterminate
浏览英文原文:ADetailedlookatOverridingtheEqualityOperator
来自:http://www.infoq.com/cn/articles/Equality-Overloading-DotNET
兄弟们,想来你们都看过了昨天的比赛了。我现在的痛苦状跟当时应该差不多。希望本版.net老师不吝赐教,为小弟这一批迷途的羊羔指一条阳光之道!您也知道:学习技术如果只有一个人摸索,那是一件多么痛苦的事情!还有,如果万辛能得名师或长者指点,那又是多么一件幸福和快乐的事情! 我觉得什么语言,精通就好,你要做的就是比其他80%的人都厉害,你就能得到只有20%的人才能得到的高薪。 ASP是把代码交给VBScript解释器或Jscript解释器来解释,当然速度没有编译过的程序快了。 ASP是把代码交给VBScript解释器或Jscript解释器来解释,当然速度没有编译过的程序快了。 众所周知,Windows以易用而出名,也因此占据不少的服务器市场。 现在主流的网站开发语言无外乎asp、php、asp.net、jsp等。 它可通过内置的组件实现更强大的功能,如使用A-DO可以轻松地访问数据库。 ASP是把代码交给VBScript解释器或Jscript解释器来解释,当然速度没有编译过的程序快了。 使用普通的文本编辑器编写,如记事本就可以完成。由脚本在服务器上而不是客户端运行,ASP所使用的脚本语言都在服务端上运行,用户端的浏览器不需要提供任何别的支持,这样大提高了用户与服务器之间的交互的速度。 主流网站开发语言之JSP:JSP和Servlet要放在一起讲,是因为它们都是Sun公司的J2EE(Java2platformEnterpriseEdition)应用体系中的一部分。 代码的可重用性差:由于是面向结构的编程方式,并且混合html,所以可能页面原型修改一点,整个程序都需要修改,更别提代码重用了。 对于中小项目来说.net技术是完全可以胜任,但为什么现在大型公司或网站都选择php或java呢?就是因为微软不够开放,没有提供从硬件到应用服务器再到业务应用的整套解决方案。 Servlet却在响应第一个请求的时候被载入,一旦Servlet被载入,便处于已执行状态。对于以后其他用户的请求,它并不打开进程,而是打开一个线程(Thread),将结果发送给客户。由于线程与线程之间可以通过生成自己的父线程(ParentThread)来实现资源共享,这样就减轻了服务器的负担,所以,JavaServlet可以用来做大规模的应用服务。 业务逻辑代码都不必做任何改动;继承性和多态性使得代码的可重用性大大提高,你可以通过继承已有的对象最大限度保护你以前的投资。并且C#和C++、Java一样提供了完善的调试/纠错体系。
页:
[1]