成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

“簡單的.NET面試題”?以及IL代碼的用途

開發(fā) 后端
一段看似簡單的VB.NET代碼,卻輸出了令人意想不到的結(jié)果。本文通過對這道“簡單的.NET面試題”進(jìn)行分析和IL代碼跟蹤,介紹了C#和VB.NET編譯器的一些不同,以及跟蹤調(diào)試技能的重要性。

.NET面試題?

我的一名很好學(xué)的學(xué)生給我發(fā)來了一封郵件,其內(nèi)容如下:

==========================================================

你好!

感謝你給我的幫助!

有一個問題向你請教:

  1. for i as integer =1 to 10  
  2.   dim a as integer  
  3.   a=a+1  
  4. next  

在第二次循環(huán)結(jié)束時,a的值為多少?你是如何理解的?

非常感謝!

                              張XX

                             2009-8-12

============================================================

這是一段VB.NET代碼,雖然我在開發(fā)中不太有可能寫過這樣子的代碼——將一個變量的定義語句放到循環(huán)語句的內(nèi)部,但作為一名老的VB程序員,這道題看上去太簡單了,答案似乎一目了然。然而,如果真是這么簡單,這名學(xué)生會費(fèi)這么大功夫給我發(fā)這樣一個郵件?

先不看答案,大家猜猜,結(jié)果是什么?

(空掉數(shù)行,別偷看答案!)

……

……

……

……

……

……

……

……

……

……

真實結(jié)果是:2!相信這是一個會讓C#程序員大感意外的結(jié)果!難道不是每次循環(huán)開始時都新定義一個變量嗎?新定義的變量應(yīng)該取默認(rèn)值0啊,為何會得到2?

有關(guān)“.NET面試題”的分析

為了便于分析,我將代碼修改了一下,同時寫了一段C#和VB.NET代碼作為對比:

VB.NET代碼:

  1. Module Module1  
  2.    
  3.     Sub Main()  
  4.         For i As Integer = 1 To 10  
  5.             Dim a As Integer 
  6.             a = a + 1  
  7.             Console.WriteLine(a)  
  8.         Next 
  9.         Console.ReadKey()  
  10.     End Sub 
  11.    
  12. End Module 
  13.   

C#代碼:

  1. class Program  
  2.     {  
  3.         static void Main(string[] args)  
  4.         {  
  5.             for (int i = 1; i <= 10; i++)  
  6.             {  
  7.                 int a = 0;  //必須初始化,否則C#編譯器報錯!  
  8.                 a=a+1;  
  9.                 Console.WriteLine(a);  
  10.             }  
  11.             Console.ReadKey();  
  12.         }  
  13.     } 

運(yùn)行結(jié)果是:VB.NET程序輸出1到10,而C#程序輸出10個“1”。

原因何在?

有的程序員可能會想到可以使用Reflector工具反匯編上述兩段代碼生成的程序集,看看原因到底是什么。

然而你會很失望,對比結(jié)果看不出有什么大的差異,甚至Reflector根據(jù)IL指令為VB.NET程序生成的C#代碼還是錯的,無法通過C#編譯器的編譯。

“.NET面試題”全跟蹤:IL代碼解讀

最后一招:祭出“終極武器”——ildasm,直接閱讀生成的IL指令。

在Release模式下,VB.NET程序生成的IL代碼如下(我加了詳細(xì)的注釋,注意紅色的指令):

  1. .method public static void  Main() cil managed  
  2. {  
  3.   .entrypoint  
  4.   .custom instance void [mscorlib]System.STAThreadAttribute::.ctor() = ( 01 00 00 00 )  
  5.   // Code size       28 (0x1c)  
  6. .maxstack  2  
  7.    
  8. //分配兩個Slot,用于保存兩個局部變量,對于整型變量,初值為0  
  9.   .locals init ([0] int32 a,   
  10.            [1] int32 i)  
  11. //將“1”保存到變量”i”中  
  12.   IL_0000:  ldc.i4.1  
  13.   IL_0001:  stloc.1  
  14. //將變量a的當(dāng)前值裝入計算堆棧  
  15.   IL_0002:  ldloc.0  
  16.  //將“1” 裝入計算堆棧  
  17.   IL_0003:  ldc.i4.1  
  18. //實現(xiàn)a=a+1,add.ovf指令從堆棧中彈出兩個操作數(shù)相加,并進(jìn)行溢出檢查  
  19.   IL_0004:  add.ovf  
  20. //結(jié)果保存回變量a中  
  21.  IL_0005:  stloc.0  
  22. //將變量a的新值裝入計算堆棧  
  23.   IL_0006:  ldloc.0  
  24. //將a的新值輸出顯示  
  25.   IL_0007:  call       void [mscorlib]System.Console::WriteLine(int32)  
  26.  //將變量i的新值裝入計算堆棧  
  27.  IL_000c:  ldloc.1  
  28. //將”1”裝入計算堆棧  
  29.   IL_000d:  ldc.i4.1  
  30. //實現(xiàn)i=i+1,循環(huán)變量自增  
  31.   IL_000e:  add.ovf  
  32.   //i的新值保存到變量i中  
  33.   IL_000f:  stloc.1  
  34. //將變量i的值裝入計算堆棧  
  35.   IL_0010:  ldloc.1  
  36. //將循環(huán)終值10壓入計算堆棧  
  37.   IL_0011:  ldc.i4.s   10  
  38. //如果i<=10,跳到指令I(lǐng)L_0002處重新執(zhí)行。  
  39.   IL_0013:  ble.s      IL_0002  
  40. //暫停顯示  
  41.   IL_0015:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()  
  42.   IL_001a:  pop  
  43. //退出  
  44.   IL_001b:  ret  
  45. // end of method Module1::Main 

而C#生成的如下,為簡潔起見,我只在關(guān)鍵語句加了注釋

  1. .method private hidebysig static void  Main(string[] args) cil managed  
  2. {  
  3.   .entrypoint  
  4.   // Code size       32 (0x20)  
  5.   .maxstack  2  
  6.   .locals init ([0] int32 i,  
  7.            [1] int32 a)  
  8. //i=1  
  9.   IL_0000:  ldc.i4.1  
  10.   IL_0001:  stloc.0  
  11. //無條件直接跳到IL_0014處!  
  12.   IL_0002:  br.s       IL_0014  
  13.    
  14. //a=0  
  15.   IL_0004:  ldc.i4.0  
  16.   IL_0005:  stloc.1  
  17. //a++  
  18.   IL_0006:  ldloc.1  
  19.   IL_0007:  ldc.i4.1  
  20.   IL_0008:  add  
  21.   IL_0009:  stloc.1  
  22. //輸出a的值  
  23.   IL_000a:  ldloc.1  
  24.   IL_000b:  call       void [mscorlib]System.Console::WriteLine(int32)  
  25. //i++  
  26.   IL_0010:  ldloc.0  
  27.   IL_0011:  ldc.i4.1  
  28.   IL_0012:  add  
  29.   IL_0013:  stloc.0  
  30.   IL_0014:  ldloc.0  
  31. //如果i<=10,跳轉(zhuǎn)到IL_0004處  
  32.   IL_0015:  ldc.i4.s   10  
  33.   IL_0017:  ble.s      IL_0004  
  34.   IL_0019:  call       valuetype [mscorlib]System.ConsoleKeyInfo [mscorlib]System.Console::ReadKey()  
  35.   IL_001e:  pop  
  36. //結(jié)束返回  
  37.   IL_001f:  ret  
  38. // end of method Program::Main  
  39.   

情況很清楚了,VB.NET編譯器充分利用了變量的默認(rèn)值,沒有生成直接的變量初始化語句,因此,它每次循環(huán)結(jié)束后跳到IL_0002處,其指令直接取出的就是變量a的當(dāng)前值,因此,每次循環(huán)的結(jié)果都可以保留,程序輸出結(jié)果“1”,“2”,……,“10”。

而C#則要求變量必須明確初始化,編譯器為變量a生成了初始化語句(IL_0004到IL_0005),而這兩個語句又在循環(huán)體內(nèi),每次循環(huán)開始a都回到初值0,因此,輸出10個“1”。

在IL代碼面前,編譯器玩的把戲被揭穿!

事實上,C#從2.0開始,就出現(xiàn)了許多讓不少初學(xué)者比較頭痛的語法,比如匿名方法、Lambda表達(dá)等,其實,只要使用Reflector或者是ildasm工具,你會發(fā)現(xiàn)這些與傳統(tǒng)語法相比“很奇怪”的新特性,在底層都會變成大家所熟悉的語法形式。

另外,從這個小實例中可以看到,掌握“比較底層”的IL編程,在了解.NET技術(shù)內(nèi)幕方面還是有幫助的。同時提醒一下.NET學(xué)習(xí)者,在學(xué)習(xí)中要重視掌握跟蹤調(diào)試的基本技能,我看到的幾乎所有的軟件高手,大都是分析問題的高手,他們高超技能之一往往表現(xiàn)為能熟練應(yīng)用各種工具深入調(diào)試程序找到問題的關(guān)鍵,進(jìn)而開發(fā)出優(yōu)秀的程序。

本文來自bitfan(數(shù)字世界一凡人)的專欄:《一道可以成為.NET面試“必殺題”的“簡單問題”》。

【編輯推薦】

  1. 大家一起探討兩道C#面試題
  2. 中高級ASP.NET程序員面試題目實例
  3. 史上最全ASP.NET面試題目集錦
  4. C#數(shù)據(jù)結(jié)構(gòu)與算法之順序表淺析
  5. C#算法一道面試題淺析
責(zé)任編輯:yangsai 來源: bitfan的博客
相關(guān)推薦

2014-09-19 11:17:48

面試題

2021-01-22 11:58:30

MySQL數(shù)據(jù)庫開發(fā)

2017-12-22 13:38:55

2020-06-04 14:40:40

面試題Vue前端

2009-08-28 09:29:02

2017-11-21 12:15:27

數(shù)據(jù)庫面試題SQL

2010-11-26 10:53:29

戴爾

2014-07-15 11:10:01

面試題面試

2020-09-21 11:10:06

Docker運(yùn)維面試

2011-03-24 13:27:37

SQL

2023-11-13 07:37:36

JS面試題線程

2009-08-01 23:17:19

ASP.NET面試題目ASP.NET

2014-12-02 10:02:30

2018-07-10 16:50:28

數(shù)據(jù)庫MySQL面試題

2021-09-09 08:54:48

SpringAOP面試題AOP事務(wù)

2009-06-02 15:30:35

Hibernate面試筆試題

2009-11-19 10:29:01

2024-11-28 08:33:16

JavaScrip事件循環(huán)this

2023-09-21 14:55:24

Web 開發(fā)TypeScript

2015-09-02 09:32:56

java線程面試
點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號

主站蜘蛛池模板: 日韩精品在线观看一区二区 | 国产精品久久久久久久久免费樱桃 | av网站在线播放 | 欧美一级免费看 | 精品欧美 | h视频在线免费观看 | 精品成人一区 | 中文字幕人成乱码在线观看 | 精产国产伦理一二三区 | av网站免费在线观看 | 久久精品这里精品 | 在线色网站 | 欧美自拍另类 | 自拍偷拍视频网 | 天堂在线中文 | 久久综合影院 | 看av网址| 色婷婷久久久久swag精品 | 亚洲视频精品 | 欧美日韩成人影院 | 中文字幕一区二区三区在线观看 | 亚洲视频免费在线播放 | 羞羞色影院 | 一区二区在线不卡 | 日本成人福利视频 | 日韩在线精品视频 | 久久躁日日躁aaaaxxxx | 久久亚洲春色中文字幕久久久 | 日韩免费网站 | 岛国精品 | 在线欧美激情 | 国产一区二区三区在线 | 热re99久久精品国产99热 | 国产成人综合在线 | 免费色网址 | 热久色| 久久精品av | 成人亚洲视频 | 奇米在线 | 男人的天堂久久 | 天天艹|