ASP.NET网页编程之关于.NET的非常处置的几个误区仓酷云
听03很多师兄说主讲老师杭城方讲课很差就连旁听也没有去了)Truly日期:2007.8.5
好久前就想写这么一篇文章,由于良多人利用.Net多年以后仍是对非常处置一孔之见的,有良多曲解,本文将解说三个罕见曲解,一个是catch的利用办法是不是准确,别的两个是try/catch的功能丧失成绩。
有些人以为上面代码就是一个catch的毛病用法:
catch(Exceptione)
{
throwe;
}起首申明,这不是一个毛病用法,可是一般来说,我们应当制止这类代码。然后要申明的是,这段代码有一个对照典范的感化就是改动非常呈现的地位,也就是能够对某类非常一致在一个地位处置。先看上面代码:
publicintGetAllCount2()
{
try
{
openDB();
inti=1;
returni;
}
catch(SqlExceptionsex)
{
throwsex;
}
catch(Exceptionex)
{
throwex;
}
}
publicintGetAllCount()
{
openDB();//这里也多是微软企业类库等
inti=1;
returni;
}
privatevoidopenDB()
{
conn.Open();
}
假定我们有一个公用办法叫openDB(),而良多办法中挪用它,当数据库翻开失利的时分,关于挪用GetAllCount办法,非常将定位于conn.Open而假如挪用GetAllCount2,那末非常定位于throwsex的地位,同时仓库信息也有所分歧,能够更快速的找到挪用办法的地位,也可在此地位举行一些毛病恢复处置。特别是我们编写一些底层类库的时分,好比Framework类库从不会把非常代码定位到Framework类库外部的某个办法下面。可是必要注重的是我们只管制止捕捉非常而不前往,比方catch(){}如许的利用就是典范的毛病利用了,由于关于Framework来说,任什么时候候体系都大概抛出一个StackOverflowException大概OutOfMemoryExcetpion而下面这段代码则埋没了这些非常,偶然候则招致一些严峻的成绩。
关于非常处置,在功能上有2点注重
第一点,在利用try/catch时,假如不产生非常,那末几近能够疏忽功能的丧失。
关于这一点,这里我们举行一些深切剖析,对此对照懂得的能够跳过本节。起首,让我们先看一下try/catch的IL体现。我们有2个办法,一个利用try/catch,而另外一个未做任那边理:
staticintTest1(inta,intb)
{
try
{
if(a>b)
returna;
returnb;
}
catch
{
return-1;
}
}
staticintTest2(inta,intb)
{
if(a>b)
returna;
returnb;
}利用ILDasm工具检察,IL代码分离以下:(这里之以是引进IL,是由于IL是对照靠近呆板汇编,以是在IL中我们能够更分明的懂得代码的实行情形,对IL没有乐趣的能够跳过此节)
.methodprivatehidebysigstaticint32Test1(int32a,
int32b)cilmanaged
{
//代码巨细30(0x1e)
.maxstack2
.localsinit(int32CS$1$0000,
boolCS$4$0001)
IL_0000:nop
.try
{
IL_0001:nop
IL_0002:ldarg.0
IL_0003:ldarg.1
IL_0004:cgt
IL_0006:ldc.i4.0
IL_0007:ceq
IL_0009:stloc.1
IL_000a:ldloc.1
IL_000b:brtrue.sIL_0011
IL_000d:ldarg.0
IL_000e:stloc.0
IL_000f:leave.sIL_001b
IL_0011:ldarg.1
IL_0012:stloc.0
IL_0013:leave.sIL_001b
}//end.try
catchSystem.Object
{
IL_0015:pop
IL_0016:nop
IL_0017:ldc.i4.m1
IL_0018:stloc.0
IL_0019:leave.sIL_001b
}//endhandler
IL_001b:nop
IL_001c:ldloc.0
IL_001d:ret
}//endofmethodProgram::Test1
Test2
.methodprivatehidebysigstaticint32Test2(int32a,
int32b)cilmanaged
{
//代码巨细22(0x16)
.maxstack2
.localsinit(int32CS$1$0000,
boolCS$4$0001)
IL_0000:nop
IL_0001:ldarg.0
IL_0002:ldarg.1
IL_0003:cgt
IL_0005:ldc.i4.0
IL_0006:ceq
IL_0008:stloc.1
IL_0009:ldloc.1
IL_000a:brtrue.sIL_0010
IL_000c:ldarg.0
IL_000d:stloc.0
IL_000e:br.sIL_0014
IL_0010:ldarg.1
IL_0011:stloc.0
IL_0012:br.sIL_0014
IL_0014:ldloc.0
IL_0015:ret
}//endofmethodProgram::Test2这里我们只需存眷红字高亮的几行便可。此处我们只体贴try区块,即未产生非常的时分,关于Test1来说,IL代码多出了8个字节来保留catch的处置代码,这一点对功能和资本几近是微乎其微的。
我们看到当Test1实行到IL_000f大概IL_0013的时分,将数据出栈并利用leave.s加入try区块转向IL_001b地点,然后将数据进栈并前往。
关于Test2来说,实行到IL_000e大概IL_0012的时分,间接加入,并将数据进栈然后前往。
这里对几个关头指令复杂先容一下
nopdonoting
stloc.0Popvaluefromstackintolocalvariable0.
ldloc.0Loadlocalvariable0ontostack.
br.stargetbranchtotarget,shortform
leave.stargetExitaprotectedregionofcode,shortform
上面我们看代码的实践运转情形,新建一个把持台Console程序,到场上面代码:
<br>
<br>点击右边图标睁开代码
staticvoidMain(string[]args)
{
inttimes=1000000;//我们将了局缩小100,0000倍
longl1,l2,l3,l4,s1,s2;
Console.WriteLine("Pressanykeytocontinue
<br>");
Console.Read();
for(intj=0;j<10;j++)
{
l1=DateTime.Now.Ticks;
for(inti=0;i<times;i++)
Test2(2,4);
l2=DateTime.Now.Ticks;
s1=l2-l1;
Console.WriteLine("timespent:"+s1);
l3=DateTime.Now.Ticks;
for(inti=0;i<times;i++)
Test1(2,4);
l4=DateTime.Now.Ticks;
s2=l4-l3;
Console.WriteLine("timespent:"+s2);
Console.WriteLine("difference:"+(s2-s1)+",rate:"+(float)(s2-s1)/s1/times);
}
}
staticintTest1(inta,intb)
{
try
{
for(inti=0;i<100;i++);//摹拟长时利用
if(a>b)
returna;
returnb;
}
catch
{
return-1;
}
}
staticintTest2(inta,intb)
{
for(inti=0;i<100;i++);//摹拟长时利用
if(a>b)
returna;
returnb;
}运转后能够看到代码的差别,一般在0.0001%的不同之内。
第二点,假如产生非常,那末激发或处置非常时,将利用大批的体系资本和实行工夫。激发非常只是为了处置的确非常的情形,而不是为了处置可预知的事务或流把持。比方,假如办法参数有效,而使用程序必要利用无效的参数挪用办法,则能够激发非常。有效的办法参数意味着呈现了非常情形。相反,用户偶然会输出有效数据,这是能够预感的,因而假如用户输出有效,则不要激发非常。在这类情形下,请供应重试机制以便用户输出无效输出。
我们常常必要将一个字符串转换为int,好比将Request.QueryString["id"]如许的字符串转换为int,在asp.net1.x时期,我们常利用以下体例
try
{
intid=Int32.Parse("123");
}
catch(){}如许的成果是假如呈现转换非常,你将不能不就义大批的体系资本来处置非常,即便你没有编写任何非常处置代码。
固然你也能够编写大批的代码来检测和转换字符串来替换try/catch体例,而从asp.net2.0今后,框架将这个检测转换历程封装到Int32.TryParse办法中,不再用糟糕的try/catch来处置了。
还要增补一点,就是finally中的代码是一直包管运转的,以是留给人人一个成绩,上面代码实行后a的值是几:
inta=2;
try
{
inti=Int32.Parse("s");
}
catch
{
a=1;
return;
}
finally
{
a=3;
}
大节:本文次要对非常处置的3个罕见曲解举行了改正。撰稿仓皇,若有疏漏,烦请指出。
参考文献:
http://msdn2.microsoft.com/zh-cn/library/system.exception(VS.80).aspx
http://msdn.microsoft.com/library/chs/default.asp?url=/library/CHS/cpguide/html/cpconexceptionsoverview.asp
《CILInstructionSetSpecification》
《AppliedMicrosoft.NETFrameworkProgramming》
批评:
#re:关于.NET的非常处置的几个误区[未登录]2007-08-0520:15|Lucifer
这个在JefferyRichter的CLRviaC#中解说的充足分明,人人能够往浏览一下!
很遗憾的是楼主的
catch(Exceptione)
{
throwe;
}
在.NET1.x版本中不克不及捕获不切合CLS的非常。而在.NET2.0中固然可以捕获一切非常,却会改动非常的肇端点。FxCop会呈报这是个毛病。
假如你要从头抛出非常,倡议接纳
catch(Exceptione)
{
throw;
}
下面的这段代码固然也会修正非常的肇端点,可是CLR却晓得原始非常被抛出时的仓库地位。
别的,非常带来的优点远远凌驾它会带来的功能丧失。#re:关于.NET的非常处置的几个误区2007-08-0520:32|寸芒
楼上的,我有贰言,固然throwe是抛出新的非常,可是这个新的非常对象仍是本来的非常。就算你在这个子catch里改动了这个非常!#re:关于.NET的非常处置的几个误区[未登录]2007-08-0520:52|Lucifer
@寸芒
我批准你的概念。
实践上,这两段代码的区分就在于CLR怎样断定非常抛出的肇端点。
可是,假如你要用throwe。FxCop就会报错。
以是,仍是保举
catch(Exceptione)
{
throw;
}
而这类捕捉一切非常再次从头抛出的举动长短常稀有的。
#re:关于.NET的非常处置的几个误区2007-08-0608:35|AndersCui
倡议:
只管不要catch像Exception如许的通用非常类;
利用throw来保护非常仓库;
假如要抛出新的非常,能够将本来的非常定为外部非常;
利用try-parse形式时注重,假如由于try操纵以外的缘故原由招致操纵失利,仍应抛出非常;
#re:关于.NET的非常处置的几个误区2007-08-0609:35|BruceLee
非常处置一向用欠好,详细是甚么,但愿总结下。
#re:关于.NET的非常处置的几个误区2007-08-0610:08|Truly
呵呵,起首看到人人积极讲话,甚感欣喜,有些人也做了深切思索,这都很好,起到了举一反三的效果。
特地说一下,下面2位的定见基础上跟我的文中所述并没有甚么收支,制止利用,改动非常地位,制止捕捉一切非常等等这都是人人承认的概念。
别的,CLRviaC#现实上就是我文中提到的参考文献中的《AppliedMicrosoft.NETFrameworkProgramming》,在撰写此文的时分,我又再次审读了非常处置一章,不外仍是感谢你的留言。
同时,我也注重到Asp.NET1.x到Asp.NET2.0今后,非常有所分歧,这一点我在测试那段代码的时分也注重到了,可是详细细节我没有往穷究。#re:关于.NET的非常处置的几个误区2007-08-0610:35|Truly
关于一篇手艺文章而言,可以留给读者一些思索空间长短常好的,明显本文到达了这一目标。关于手艺,我也力争制止引诱、误导读者,多半情形我们剖析道理,研讨框架。这里剖析出了try/catch时的情形,至于孰优孰劣,大概是长处多仍是弱点多,这就交给读者见仁见智,我不喜好教条式的论道本文链接:http://www.ckuyun.com/Truly/archive/2007/08/05/843837.htmlC#中有两处地方用到new关键字,第一处也是最常见的一处是用在调用构造函数的时候,这种情况也是大家见的最多的一种。另一处是用在派生类中,作用有隐藏成员,切断继承关系等,相信第二处的用法大家明显要比第一处生疏。 ASP.net的服务器,要求安装一个.net环境,当然我这里指的是windows系统,顺便点一下,.net只能放在windows环境里来运行。Asp.net1.1的就装Framework1.1,Asp.net2.0的就装Framework2.0。 是目前ASP在UNIX/Linux上的应用可以说几乎为0)。所以平台的局限性和ASP自身的安全性限制了ASP的广泛应用。 HTML:当然这是网页最基本的语言,每一个服务器语言都需要它的支持,要学习,这个肯定是开始,不说了. asp.net空间的支持有:ASP.NET1.1/虚拟目录/MicrosoftFrontPage2000扩展/CDONTS,同时他的网站上也提供了Asp.net的使用详解和程序源代码,相信对使用ASP.NET编程的程序员来说会非常有用哦! Servlet的形式和前面讲的CGI差不多,它是HTML代码和后台程序分开的。它们的启动原理也差不多,都是服务器接到客户端的请求后,进行应答。不同的是,CGI对每个客户请求都打开一个进程(Process)。 网页从开始简单的hmtl到复杂的服务语言,走过了10多个年头,各种技术层出不穷,单个的主流技术也在不断翻新的版本,现在分析下各种语言的区别、优势、劣势、开发注意事项! 众所周知,Windows以易用而出名,也因此占据不少的服务器市场。 ASP.net的速度是ASP不能比拟的。ASP.net是编译语言,所以,当第一次加载的时候,它会把所有的程序进行编译(其中包括worker进程,还有对语法进行编译,形成一个程序集),当程序编译后,执行速度几乎为0。 可以通过在现有ASP应用程序中逐渐添加ASP.NET功能,随时增强ASP应用程序的功能。ASP.NET是一个已编译的、基于.NET的环境,可以用任何与.NET兼容的语言(包括VisualBasic.NET、C#和JScript.NET.)创作应用程序。另外,任何ASP.NET应用程序都可以使用整个.NETFramework。开发人员可以方便地获得这些技术的优点,其中包括托管的公共语言运行库环境、类型安全、继承等等。 Servlet却在响应第一个请求的时候被载入,一旦Servlet被载入,便处于已执行状态。对于以后其他用户的请求,它并不打开进程,而是打开一个线程(Thread),将结果发送给客户。由于线程与线程之间可以通过生成自己的父线程(ParentThread)来实现资源共享,这样就减轻了服务器的负担,所以,JavaServlet可以用来做大规模的应用服务。 ASP是把代码交给VBScript解释器或Jscript解释器来解释,当然速度没有编译过的程序快了。 ASP.net1.1和2.0在程序上的语法也有很大不同,现在2.0属于新出来的,不知道半年后会不会有3.0(说笑一下)。Windows2003系统自动支持ASP和ASP.net环境,不用安装任何程序。Asp.net属于编译语言。ASP的最大不同(ASP属于解释语言)。 JSP/Servlet虽然在国内目前的应用并不广泛,但是其前途不可限量。 在一个项目中谁敢保证每天几千万甚至几亿条的数据不丢失?谁敢保证应用的高可靠性?有可以借签的项目吗? 主流网站开发语言之JSP:JSP和Servlet要放在一起讲,是因为它们都是Sun公司的J2EE(Java2platformEnterpriseEdition)应用体系中的一部分。 它可通过内置的组件实现更强大的功能,如使用A-DO可以轻松地访问数据库。 以上是语言本身的弱点,在功能方面ASP同样存在问题,第一是功能太弱,一些底层操作只能通过组件来完成,在这点上是远远比不上PHP/JSP,其次就是缺乏完善的纠错/调试功能,这点上ASP/PHP/JSP差不多。 业务逻辑代码都不必做任何改动;继承性和多态性使得代码的可重用性大大提高,你可以通过继承已有的对象最大限度保护你以前的投资。并且C#和C++、Java一样提供了完善的调试/纠错体系。 代码的可重用性差:由于是面向结构的编程方式,并且混合html,所以可能页面原型修改一点,整个程序都需要修改,更别提代码重用了。
页:
[1]
2