ASP.NET编程:[你必需晓得的.NET]第十二回:参数之惑――传送的艺术(下)仓酷云 ...
前天傍晚我发表了《net网页编程的跨平台就是一句谎言。》,原本就是周末闲来无事,发表一篇略带争议性的博文让大家都来吵吵架,发表自己的看法,根本就没想着谁把谁打倒,一个行业或者是技术阵营是无法用短期口水仗打到对手的。系列文章目次索引:《你必需晓得的.NET》本文将先容以下内容:
[*]按值传送与按援用传送深论
[*]ref和out对照
[*]参数使用浅析
<br>
接上篇持续,『第十一回:参数之惑---传送的艺术(上)』
4.2援用范例参数的按值传送
当传送的参数为援用范例时,传送和操纵的是指向对象的援用,这意味着办法操纵能够改动本来的对象,可是值得思索的是该援用大概说指针自己仍是按值传送的。因而,我们在此必需分明的懂得以下两个最基本的成绩:
[*]援用范例参数的按值传送和按援用传送的区分?
[*]string范例作为特别的援用范例,在按值传送时体现的特别性又怎样注释?
起首,我们从基础的了解动手来懂得援用范例参数按值传送的实质地点,复杂的说对象作为参数传送时,实行的是对对象地点的拷贝,操纵的是该拷贝地点。这在实质上和值范例参数按值传送是不异的,都是按值传送。分歧的是值范例的“值”为范例实例,而援用范例的“值”为援用地点。因而,假如参数为援用范例时,在挪用方代码中,能够改动援用的指向,从而使得原对象的指向产生改动,如例所示:
<br>
<br>援用范例参数的按值传送
//FileName:Anytao.net.My_Must_net
//Description:The.NETwhatyoushouldknowofarguments.
//Release:2007/07/011.0
//Copyright:(C)2007Anytao.comhttp://www.anytao.com
usingSystem;
namespaceAnytao.net.My_Must_net
{
classArgs
{
publicstaticvoidMain()
{
ArgsByRefabf=newArgsByRef();
AddRef(abf);
Console.WriteLine(abf.i);
}
privatestaticvoidAddRef(ArgsByRefabf)
{
abf.i=20;
Console.WriteLine(abf.i);
}
}
classArgsByRef
{
publicinti=10;
}
}
因而,我们进一步能够总结为:按值传送的本色的是传送值,分歧的是这个值在值范例和援用范例的体现是分歧的:参数为值范例时,“值”为实例自己,因而传送的是实例拷贝,不会对本来的实例发生影响;参数为援用范例时,“值”为对象援用,因而传送的是援用地点拷贝,会改动本来对象的援用指向,这是两者在一致观点上的体现区分,了解了实质也就捉住了本源。关于值范例和援用范例的观点能够参考《第八回:咀嚼范例---值范例与援用范例(上)-内存有理》《第九回:咀嚼范例---值范例与援用范例(中)-划定规矩无边》《第十回:咀嚼范例---值范例与援用范例(下)-使用征途》,信任能够经由过程对系列中的值范例与援用范例的3篇的了解,加深对参数传送之惑的平反。
懂得了援用范例参数按值传送的本色,我们有需要再引进另外一个参数传送的观点,那就是:按援用传送,一般称为援用参数。这两者的实质区分能够小结为:
[*]援用范例参数的按值传送,传送的是参数自己的值,也就是下面提到的对象的援用;
[*]按援用传送,传送的不是参数自己的值,而是参数的地点。假如参数为值范例,则传送的是该值范例的地点;假如参数为援用范例,则传送的是对象援用的地点。
关于援用参数的具体观点,我们即刻就睁开来会商,不外仍是先剖析一下string范例的特别性,事实特别在那里?
关于string的会商,在自己拙作《第九回:咀嚼范例---值范例与援用范例(中)-划定规矩无边》已有了会商,也就是开篇报告的本文成文的汗青,以是在上述剖析的基本上,我以为应当更能对第九回的成绩,做以改正。
string自己为援用范例,因而从本文的剖析中可知,关于形如
staticvoidShowInfo(stringaStr){...}
的传送情势,能够分明的晓得这是按值传送,也就是本文总结的援用范例参数的按值传送。因而,传送的是aStr对象的值,也就是aStr援用指针。接上去我们看看上面的示例来剖析,为何string范例在传送时体现出特别性及其发生的缘故原由?
//FileName:Anytao.net.My_Must_net
//Description:The.NETwhatyoushouldknowofarguments.
//Release:2007/07/051.0
//Copyright:(C)2007Anytao.comhttp://www.anytao.com
usingSystem;
namespaceAnytao.net.My_Must_net
{
classhow2str
{
staticvoidMain()
{
stringstr="OldString";
ChangeStr(str);
Console.WriteLine(str);
}
staticvoidChangeStr(stringaStr)
{
aStr="ChangingString";
Console.WriteLine(aStr);
}
}
}
上面对上述示例的实行历程扼要剖析一下:起首,stringstr="OldString"发生了一个新的string对象,如图暗示:
<br>
然后实行ChangeStr(aStr),也就是举行援用范例参数的按值传送,我们夸大说这里传送的是援用范例的援用值,也就是地点指针;然后挪用ChangeStr办法,历程aStr="ChangingString"完成了以下的操纵,先在新的一个地点天生一个string对象,该新对象的值为"ChangingString",援用地点为0x06赋给参数aStr,因而会改动aStr的指向,可是并没有改动本来办法外str的援用地点,实行历程能够暗示为:
<br>
因而实行了局便可想而知,我们从剖析历程就能够发明string作为援用范例,在按值传送过程当中和其他援用范例是一样的。假如必要完成ChangeStr()挪用后,改动本来str的值,就必需利用ref大概out润色符,依照按援用传送的体例来举行就能够了,届时aStr="ChangingString"改动的是str的援用,也就改动了str的指向,详细的剖析但愿人人经由过程接上去的按援用传送的揭密以后,能够自行剖析。
4.3按援用传送之ref和out
不论是值范例仍是援用范例,按援用传送必需以ref大概out关头字来润色,其划定规矩是:
[*]办法界说和办法挪用必需同时显现的利用ref大概out,不然将招致编译毛病;
[*]CRL同意经由过程out大概ref参数来重载办法,比方:
//FileName:Anytao.net.My_Must_net
//Description:The.NETwhatyoushouldknowofarguments.
//Release:2007/07/031.0
//Copyright:(C)2007Anytao.comhttp://www.anytao.com
usingSystem;
namespaceAnytao.net.My_Must_net._11_Args
{
classTestRefAndOut
{
staticvoidShowInfo(stringstr)
{
Console.WriteLine(str);
}
staticvoidShowInfo(refstringstr)
{
Console.WriteLine(str);
}
}
}
固然,按援用传送时,不论参数是值范例仍是援用范例,在实质上也是不异的,这就是:ref和out关头字将告知编译器,办法传送的是参数地点,而不是参数自己。了解了这一点也就捉住了按援用传送的实质,因而依据这一实质结论我们能够得出以下更分明的说法,这就是:
[*]不论参数自己是值范例仍是援用范例,按援用传送时,传送的是参数的地点,也就是实例的指针。
[*]假如参数是值范例,则按援用传送时,传送的是值范例变量的援用,因而在效果上相似于援用范例参数的按值传送体例,实在质能够剖析为:值范例的按援用传送体例,完成的是对值范例参数实例的间接操纵,办法挪用方为该实例分派内存,而被挪用办法操纵该内存,也就是值范例的地点;而援用范例参数的按值传送体例,完成的是对援用范例的“值”援用指针的操纵。比方:
//FileName:Anytao.net.My_Must_net
//Description:The.NETwhatyoushouldknowofarguments.
//Release:2007/07/061.0
//Copyright:(C)2007Anytao.comhttp://www.anytao.com
usingSystem;
namespaceAnytao.net.My_Must_net
{
classTestArgs
{
staticvoidMain(string[]args)
{
inti=100;
stringstr="One";
ChangeByValue(refi);
ChangeByRef(refstr);
Console.WriteLine(i);
Console.WriteLine(str);
}
staticvoidChangeByValue(refintiVlaue)
{
iVlaue=200;
}
staticvoidChangeByRef(refstringsValue)
{
sValue="Onemore.";
}
}
}
假如参数是援用范例,则按援用传送时,传送的是援用的援用而不是援用自己,相似于指针的指针观点。示例只需将上述string传送示例中的ChangeStr加上ref润色便可。
上面我们再进一步对ref和out的区分做以交卸,就基础论述分明了按援用传送的精要地点,能够总结为:
[*]不异点:从CRL角度来讲,ref和out都是唆使编译器传送实例指针,在体现举动上是不异的。最能证实的示例是,CRL同意经由过程ref和out来完成办法重载,可是又不同意经由过程辨别ref和out来完成办法重载,因而从编译角度来看,不论是ref仍是out,编译以后的代码是完整不异的。比方:
//FileName:Anytao.net.My_Must_net
//Description:The.NETwhatyoushouldknowofarguments.
//Release:2007/07/031.0
//Copyright:(C)2007Anytao.comhttp://www.anytao.com
usingSystem;
namespaceAnytao.net.My_Must_net._11_Args
{
classTestRefAndOut
{
staticvoidShowInfo(stringstr)
{
Console.WriteLine(str);
}
staticvoidShowInfo(refstringstr)
{
Console.WriteLine(str);
}
staticvoidShowInfo(outstringstr)
{
str="Hello,anytao.";
Console.WriteLine(str);
}
}
}
编译器将提醒:“ShowInfo”不克不及界说仅在ref和out上有不同的重载办法。
[*]分歧点:利用的机制分歧。ref请求传送之前的参数必需起首显现初始化,而out不必要。也就是说,利用ref的参数必需是一个实践的对象,而不克不及指向null;而利用out的参数能够承受指向null的对象,然后在挪用办法外部必需完成对象的实体化。
5.结论
完成了对值范例与援用范例的叙述,在这些常识堆集的基本上,本文希冀经由过程深切的叙述来进一步的分享参数传送的艺术,解开层层困惑的面纱。从切磋成绩的角度来讲,参数传送的各种误区实在根植与对值范例和援用范例的实质了解上,因而完成了对范例成绩的切磋再进进参数传送的迷宫,我们才会加倍熟能生巧。我想,这类切磋成绩的体例,也恰是我们追逐成绩的体例,深切进进.NET的初级殿堂是绕不开这一选择的。
参考文献
(USA)JeffreyRichter,AppliedMicrosoft.NETFrameworkProgramming
(USA)DavidChappell,Understanding.NET
ASP.net1.1和2.0在程序上的语法也有很大不同,现在2.0属于新出来的,不知道半年后会不会有3.0(说笑一下)。Windows2003系统自动支持ASP和ASP.net环境,不用安装任何程序。Asp.net属于编译语言。ASP的最大不同(ASP属于解释语言)。 由于JSP/Servlet都是基于Java的,所以它们也有Java语言的最大优点——平台无关性,也就是所谓的“一次编写,随处运行(WORA–WriteOnce,RunAnywhere)”。除了这个优点,JSP/Servlet的效率以及安全性也是相当惊人的。 ASP是把代码交给VBScript解释器或Jscript解释器来解释,当然速度没有编译过的程序快了。 对于中小项目来说.net技术是完全可以胜任,但为什么现在大型公司或网站都选择php或java呢?就是因为微软不够开放,没有提供从硬件到应用服务器再到业务应用的整套解决方案。 Servlet的形式和前面讲的CGI差不多,它是HTML代码和后台程序分开的。它们的启动原理也差不多,都是服务器接到客户端的请求后,进行应答。不同的是,CGI对每个客户请求都打开一个进程(Process)。 HTML:当然这是网页最基本的语言,每一个服务器语言都需要它的支持,要学习,这个肯定是开始,不说了. 代码的可重用性差:由于是面向结构的编程方式,并且混合html,所以可能页面原型修改一点,整个程序都需要修改,更别提代码重用了。 同时也感谢博客园给我们这个平台,也感谢博客园的编辑们做成专题引来这么多高人指点。 代码逻辑混乱,难于管理:由于ASP是脚本语言混合html编程,所以你很难看清代码的逻辑关系,并且随着程序的复杂性增加,使得代码的管理十分困难,甚至超出一个程序员所能达到的管理能力,从而造成出错或这样那样的问题。
页:
[1]