本文將介紹以下內(nèi)容:
1. 引言 園子里好像沒(méi)有或者很少把new關(guān)鍵字拿出來(lái)說(shuō)的,,那我就占個(gè)先機(jī)吧,呵呵,。那么,我們到底有必要將一個(gè)關(guān)鍵字拿出來(lái)長(zhǎng)篇大論嗎,?看來(lái)是個(gè)問(wèn)題,。回答的關(guān)鍵是:你真的理解了new嗎?如果是,,那請(qǐng)不要浪費(fèi)時(shí)間,,如果不是,那請(qǐng)繼續(xù)本文的循序之旅,。 下面幾個(gè) 問(wèn)題可以大概的考察你對(duì)new的掌握,,開篇之前,希望大家做個(gè)檢驗(yàn),,如果通過(guò)了,,直接關(guān)掉本頁(yè)即可。如果沒(méi)有通過(guò),,希望本文的闡述能幫你找出答案,。
2. 基本概念 一般說(shuō)來(lái),,new關(guān)鍵字在.NET中用于以下幾個(gè)場(chǎng)合,,這是MSDN的典型解釋:
本文的重點(diǎn)內(nèi)容,,本文在下一節(jié)來(lái)重點(diǎn)考慮。
作為修飾符,基本的規(guī)則可以總結(jié)為:實(shí)現(xiàn)派生類中隱藏方法,,則基類方法必須定義為virtual,;new作為修飾符,實(shí)現(xiàn)隱藏基類成員時(shí),,不可和override共存,,原因是這兩者語(yǔ)義相斥:new用于實(shí)現(xiàn)創(chuàng)建一個(gè)新成員,同時(shí)隱藏基類的同名成員,;而override用于實(shí)現(xiàn)對(duì)基類成員的擴(kuò)展,。 另外,如果在子類中隱藏了基類的數(shù)據(jù)成員,那么對(duì)基類原數(shù)據(jù)成員的訪問(wèn),,可以通過(guò)base修飾符來(lái)完成,。 例如: new作為修飾符
using System; namespace Anytao.net.My_Must_net { class Number { public static int i = 123; public void ShowInfo() { Console.WriteLine("base class---"); } public virtual void ShowNumber() { Console.WriteLine(i.ToString()); } } class IntNumber : Number { new public static int i = 456; public new virtual void ShowInfo() { Console.WriteLine("Derived class---"); } public override void ShowNumber() { Console.WriteLine("Base number is {0}", Number.i.ToString()); Console.WriteLine("New number is {0}", i.ToString()); } } class Tester { public static void Main(string[] args) { Number num = new Number(); num.ShowNumber(); IntNumber intNum = new IntNumber(); intNum.ShowNumber(); Number number = new IntNumber(); //究竟調(diào)用了誰(shuí)? number.ShowInfo(); //究竟調(diào)用了誰(shuí),? number.ShowNumber(); } } }
MSDN中的定義是:new 約束指定泛型類聲明中的任何類型參數(shù)都必須有公共的無(wú)參數(shù)構(gòu)造函數(shù),。當(dāng)泛型類創(chuàng)建類型的新實(shí)例時(shí),,將此約束應(yīng)用于類型參數(shù)。 注意:new作為約束和其他約束共存時(shí),,必須在最后指定,。 其定義方式為: class Genericer<T> where T : new()
{ public T GetItem() { return new T(); } }
實(shí)現(xiàn)方式為: class MyCls
{ private string _name; public MyCls() { _name = "Emma"; } } class MyGenericTester
{ public static void Main(string[] args) { Genericer<MyCls> MyGen = new Genericer<MyCls>(); Console.WriteLine(MyGen.GetItem().Name); } }
3. 深入淺出 作為修飾符和約束的情況,,不是很難理解的話題,,正如我們看到本文開篇提出的問(wèn)題,也大多集中在new作為運(yùn)算符的情況,,因此我們研究的重點(diǎn)就是揭開new作為運(yùn)算符的前世今生,。 Jeffrey Richter在其著作中,極力推薦讀者使用ILDASM工具查看IL語(yǔ)言細(xì)節(jié),,從而提高對(duì).NET的深入探究,,在我認(rèn)為這真是一條不錯(cuò)的建議,也給了自己很多提高的空間挖掘,。因此,,以下是本人的一點(diǎn)建議,,我將在后續(xù)的系列中,,關(guān)于學(xué)習(xí)方法論的討論中深入探討,這里只是順便小議,,希望有益于大家,。 文歸正題,,new運(yùn)算符用于返回一個(gè)引用,,指向系統(tǒng)分配的托管堆的內(nèi)存地址。因此,在此我們以Reflector工具,,來(lái)了解以下new操作符執(zhí)行的背后,,隱藏著什么玄機(jī)。 首先我們實(shí)現(xiàn)一段最簡(jiǎn)單的代碼,,然后分析其元數(shù)據(jù)的實(shí)現(xiàn)細(xì)節(jié),,來(lái)探求new在創(chuàng)建對(duì)象時(shí)到做了什么? new作為運(yùn)算符
using System; namespace Anytao.net.My_Must_net { class MyClass { private int _id; public MyClass(int id) { _id = id; } } struct MyStruct { private string _name; public MyStruct(string name) { _name = name; } } class NewReflecting { public static void Main(string[] args) { int i; int j = new int(); MyClass mClass = new MyClass(123); MyStruct mStruct = new MyStruct("My Struct"); } } }
使用Reflector工具反編譯產(chǎn)生的IL代碼如下為: IL元數(shù)據(jù)分析
.method public hidebysig static void Main(string[] args) cil managed { .entrypoint .maxstack 2 .locals init ( [0] int32 num, [1] int32 num2, [2] class Anytao.net.My_Must_net._05_new.MyClass class2, [3] valuetype Anytao.net.My_Must_net._05_new.MyStruct struct2) L_0000: nop //初始化j為0 L_0001: ldc.i4.0 L_0002: stloc.1 //使用newobj指令創(chuàng)建新的對(duì)象,,并調(diào)用構(gòu)造函數(shù)以0x76(123的16進(jìn)制)初始化 L_0003: ldc.i4.s 0x7b L_0005: newobj instance void Anytao.net.My_Must_net._05_new.MyClass::.ctor(int32) L_000a: stloc.2 //加載“My Struct” L_000b: ldloca.s struct2 L_000d: ldstr "My Struct" //調(diào)用構(gòu)造函數(shù)執(zhí)行初始化 L_0012: call instance void Anytao.net.My_Must_net._05_new.MyStruct::.ctor(string) L_0017: nop L_0018: ret }
從而可以得出以下結(jié)論:
另外還有以下規(guī)則要多加注意:
對(duì)于基本類型來(lái)說(shuō),,使用new操作符來(lái)進(jìn)行初始化的好處是,某些構(gòu)造函數(shù)可以完成更優(yōu)越的初始化操作,,而避免了不高明的選擇,,例如: string str = new string(‘*‘, 100);
string str = new string(new char[] {‘a‘, ‘b‘, ‘c‘});
而不是 string str = "***************************************";
4. 結(jié)論 我能說(shuō)的就這么多了,至于透了沒(méi)透,,作者的能量也就這么多了,。希望園子的大牛們常來(lái)扔塊磚頭,對(duì)我也是一種莫大的促進(jìn),。但是作為基本的原理和應(yīng)用,,我想對(duì)大部分的需求是滿足了,。希望這種力求深入淺出的介紹,能給你分享new關(guān)鍵字和其本質(zhì)的來(lái)龍去脈能有所幫助,。 言歸正傳,,開篇的幾個(gè)題目,不知讀者是否有了各自的答案,,我們不妨?xí)乘?,做更深入的討論,以便揭開其真實(shí)的面紗,。 參考文獻(xiàn) (USA)Stanley B.Lippman, C# Primer (USA)David Chappell Understanding .NET 廣而告之 [預(yù)告] 另外鑒于前幾個(gè)主題的討論中,,不管是類型、關(guān)鍵字等都涉及到引用類型和值類型的話題,,我將于近期發(fā)表相關(guān)內(nèi)容的探討,,同時(shí)還有其他的關(guān)鍵字值得研究,這是本系列近期動(dòng)向,,給自己做個(gè)廣告,。祝各位愉快。 [聲明] 本文的關(guān)鍵字new指的是C#中的關(guān)鍵字概念,,并非一般意義上的.NET CRL范疇,,之所以將這個(gè)主題加入本系列,是基于在.NET體系下開發(fā)的我們,,何言能逃得過(guò)基本語(yǔ)言的只是要點(diǎn),。所以大可不必追究什么是.NET,什么是C#的話題,,希望大家理清概念,,有的放肆。 |
|