3/20/2009

[ C# ] 編碼命名規範

[轉貼http://www.purecs.net/thread/topic684_1.aspx]抨擊匈牙利命名法

匈牙利命名法是一種編程時的命名規範。命名規範是程序書寫規範中最重要也是最富爭議的地方,自古乃兵家必爭之地。命名規範有何用?四個字:名正言順。用二分法,

命名規範分為好的命名規範和壞的命名規範,()絡育Z|_%$J也就是說名正言順的命名規範和名不正言不順的命名規範。好的舞鞋是讓舞者感覺不到其存在的舞鞋,壞的舞鞋是讓舞者帶著鐐銬起舞。一個壞的命名規範具有的破壞力比一個好的命名規範具有的創造力要大得多。

本文要證明的是:匈牙利命名法是一個壞的命名規範。本文的作用範圍為靜態強類型編程語言。本文的分析範本為C語言和C++語言。下文中的匈法為匈牙利命名法的簡稱。

一 匈牙利命名法的成本

匈法的表現形式為給變量名附加上類型名前綴,例如:nFoo,szFoo,pFoo,cpFoo分別表示整型變量,字符串型變量,指針型變量和常指 針型變量。可以看出,匈法將變量的類型信息從單一地點(聲明變量處)複製到了多個地點(使用變量處),這是冗餘法。冗餘法的成本之一是要維護副本的一致 性。這個成本在編寫和維護代碼的過程中需要改變變量的類型時付出。冗餘法的成本之二是佔用了額外的空間。一個優秀的書寫者會自覺地遵從一個法則:代碼最小 組織單位的長度以30個自然行以下為宜,如果超過50行就應該重新組織。一個變量的書寫空間會給這一法則添加不必要的難度。

二 匈牙利命名法的收益

這裡要證明匈牙利命名法的收益是含糊的,無法預期的。

範本1:strcpy(pstrFoo,pcstrFoo2) Vs strcpy(foo,foo2)
匈法在這裡有什麼收益呢?我看不到。沒有一個程序員會承認自己不知道strcpy函數的參數類型吧。

範本2:unknown_function(nFoo) Vs unknown_function(foo)
匈法在這裡有什麼收益呢?我看不到。對於一個不知道確定類型的函數,t.-.-7`FxgV網管程 序員應該去查看該函數的文檔,這是一種成本。使用匈法的唯一好處是看代碼的人知道這個函數要求一個整型參數,這又有什麼用處呢?函數是一種接口,參數的類 型僅僅是接口中的一小部分。諸如函數的功能、出口信息、線程安全性、異常安全性、參數合法性等重要信息還是必須查閱文檔。

範本3:nFoo=nBar Vs foo=bar
匈法在這裡有什麼收益呢?我看不到。使用匈法的唯一好處是看代碼的人知道這裡發生了一個整型變量的複製動作,聽起來沒什麼問題,可以安心睡大覺了。如果他看到的是nFoo=szBar,可能會從美夢中驚醒。且慢,事情真的會是這樣嗎?我想首先被驚醒的應該是編譯器。另一方面,nFoo=nBar只是在語法上合法而已,看代碼的人真正關心的是語義的合法性,匈法對此毫無幫助。另一方面,一個優秀的書寫者會自覺地遵從一個法則:代碼最小組織單位中的臨時變量以一兩個為宜,

提T網件軟B'絡E$9

如果超過三個就應該重新組織。結合前述第一個法則,可以得出這樣的結論:易於理解的代碼本身就應該是易於理解的,這是代碼的內建高質量。好的命名規範對內建高質量的助益相當有限,而壞的命名規範對內建高質量的損害比人們想像的要大。
三 匈牙利命名法的實施

這裡要證明匈牙利命名法在C語言是難以實施的,在C++語言中是無法實施的。從邏輯上講,對匈法的收益做出否定的結論以後,再來論證匈法的可行性,是畫蛇添足。不過有鑑於小馬哥曾讓已射殺之敵死灰復燃,我還是再踏上一支腳為妙。

前面講過,匈法是類型系統的冗餘,所以實施匈法的關鍵是我們是否能夠精確地對類型系統進行複製。這取決於類型系統的複雜性。

先來看看C語言:

1.內置類型:int,char,float,double 複製為 n,ch,f,d?好像沒有什麼問題。不過誰來告訴我void應該怎麼表示?
2.組合類型:array,union,enum,struct 複製為 a,u,e,s?好像比較彆扭。
這裡的難點不是為主類型取名,而是為副類型取名。an表示整型數組?sfoo,sbar表示結構foo,結構bar?ausfoo表示聯合結構foo數組?累不累啊。
3.特殊類型:pointer。pointer在理論上應該是組合類型,供^_的C!]ZIcBuRT但是在C語言中可以認為是內置類型,因為C語言並沒有非常嚴格地區分不同的指針類型。下面開始表演:pausfoo表示聯合結構foo數組指針?ppp表示指針的指針的指針?

噩夢還沒有結束,再來看看類型系統更阿為豐富的C++語言:

1.class:如果說C語言中的struct還可以用stru搪塞過去的話,不要夢想用cls來搪塞C++中的class。嚴格地講,class 根本就並不是一個類型,而是創造類型的工具,在C++中,語言內置類型的數量和class創造的用戶自定義類型的數量相比完全可以忽略不計。 stdvectorFoo表示標準庫向量類型變量Foo?瘋狂的念頭。
2.命名空間:boostfilesystemiteratorFoo,表示boost空間filesystem子空間遍歷目錄類型變量Foo?程序員要崩潰了。
3.模板:你記得std::map<:string,std::string>類型的確切名字嗎?我是記不得了,好像超過255個字符,還是饒了我吧。
4. 模板參數:template const T& max(const T& a, const T& b, BinaryPredicate comp) 聰明的你,請用匈法為T命名。上帝在發笑。
5.類型修飾:static,extern,mutable,register,volatile,const,short,long,unsigned 噩夢加上修飾是什麼?還是噩夢。

你願意做鐐銬上的舞者嗎?

[問題解決]LC.exe以返回碼-1結束

許可證編譯器 (Lc.exe) 已退出,代碼 -1 可能的原因是:在你的專案中引用了第三方元件,並且這個第三方元件是個商業組件,他在元件的主使用類定義了LicenseProvider(typeof(LicFileLicenseProvider))這個Attribute。 VS2005在編譯時檢測到這個類的時候,會檢查到元件使用的是LicFileLicenseProvider這個屬性,表示有元件使用的是把許可的輔助資訊保存在license.licx文件中,這個文件保存在vs2005中解決方案資源管理器中的Properties文件夾內。 這個檔的內容實際上是個引用,他保存著你使用的第三方元件主使用類的名稱空間+類名+檔案名+文化+PublicKeyToken資訊,這個檔是自動生成的。如果這個資訊與你使用的元件dll中的實際內容不匹配,則lc.exe就會出現這個錯誤資訊。這個資訊出現的原因是你在專案中使用了商業元件的測試版,而在發佈的時候使用的是哪個商業組件的破解版。大部分的商業組件經過破解的時候,強名稱簽名就會消失,所以破解的元件與原來的測試版元件的引用資訊是完全不同的。故每次編譯的時候,vs2005自動調用語言編譯器之前會調用lc(許可編譯器),就會出現-1錯誤。解決方法就是把Properties檔下的license.licx給刪除,然後打開設計頁面,重新編譯就ok了。,如果還出現這個問題的話,必須將你的破解版的哪個元件使用lidism給翻譯成il語言,然後用ilasm重新編譯成dll,在編譯的時候加入 /key=[你的強名稱檔].snk 參數,自己加入強名稱簽名,然後使用vs2005重新編譯,就可以成功了。

1.關閉 VS2005 。

2.到專案的所在目錄刪除 license.licx 檔案。

3.開啟 VS2005 。

4.執行重建該專案,此時在「方案總管」會出現 license.licx 驚嘆號, 對 license.licx 按滑鼠右鍵,選擇刪除,再重建該專案就 OK 了。

圖形用戶端、資訊清單產生和編輯工具 (MageUI.exe)

.NET Framework 工具
圖形用戶端、資訊清單產生和編輯工具 (MageUI.exe)

MageUI.exe 所支援的功能與命令列工具 Mage.exe 相同,不過 MageUI.exe 具有 Windows Form 架構的使用者介面 (UI)。您可以利用這個工具來建立、編輯和簽章部署與應用程式資訊清單。

可用的功能表和工具列項目如下。

部署資訊清單
建立新的部署資訊清單。

應用程式資訊清單
建立新的應用程式資訊清單。

開啟
開啟現有的部署資訊清單、應用程式資訊清單或信任授權以進行編輯。

儲存
將目前使用者輸入焦點所在的文件儲存至磁碟中。

另存新檔
將檔案儲存至磁碟,可讓您提供新的檔案名稱和 (或) 位置。

全部儲存
將 MageUI.exe 中目前開啟的所有檔案所進行的變更儲存起來。

關閉
關閉開啟的檔案。

如果檔案在關閉之前做過修改,MageUI.exe 會提示您使用公開金鑰 (Public Key)、金鑰組 (Key Pair) 或預存的憑證,重新替這個檔案簽章。

結束
結束 MageUI.exe。

剪下
從應用程式中移除目前選取的文字,然後移至系統剪貼簿。

複製
將目前選取的文字複製至系統剪貼簿。

貼上
將文字從系統剪貼簿貼到目前現用的文字項目上。

刪除
刪除清單中目前選取的項目,例如 [部署資訊清單] 索引標籤上的信任授權。如需詳細資訊,請參閱 MageUI.exe 部署資訊清單索引標籤。

喜好設定
開啟 [喜好設定] 對話方塊。如需詳細資訊,請參閱下一節。

全部關閉
關閉 MageUI.exe 中目前開啟的所有檔案。如果有一或多個檔案需要進行儲存,MageUI.exe 會提示您儲存這些檔案。MageUI.exe 也會提示您選取簽章密鑰,以處理每個未簽章或變更過的檔案。

內容
開啟這一份說明文件。

關於
顯示 MageUI.exe 的版本和著作權資訊。

喜好設定對話方塊
[喜好設定] 對話方塊包含下列項目。

儲存時簽章
每當您儲存修改內容時,都會提示您替檔案簽章。

使用預設簽章密鑰
使用 [金鑰檔] 文字方塊中所輸入的金鑰,替所有檔案簽章。在選取 [儲存時簽章] 的情況下,如果選取這個選項,則當您儲存檔案時,原本會出現的簽章提示就不會出現。請使用 [金鑰檔] 文字方塊旁的 [瀏覽] 按鈕來選取金鑰檔。

簽章選項對話方塊
首次儲存資訊清單或信任授權,或是變更資訊清單或信任授權時,[簽章選項] 對話方塊會隨即出現。但是您必須在 [喜好設定] 對話方塊中選取 [儲存時簽章資訊清單] 選項,這個對話方塊才會出現。

這個對話方塊包含下列項目。

使用憑證檔簽章
使用儲存於檔案系統的數位憑證替資訊清單簽章。

檔案
提供一個區域,以便於輸入表示憑證的 .pfx 檔案路徑。

...
開啟 [選擇檔案] 對話方塊,選取現有的 .pfx 檔。

新增
產生新的 .pfx,這個檔案無法透過憑證授權單位 (CA) 進行驗證。如需簽章 ClickOnce 部署時所用之憑證類型的詳細資訊,請參閱受信任的應用程式部署概觀。

密碼
提供區域以便輸入密碼,此密碼可以在以這個憑證簽章時使用。如果不適用,此項目可以保持空白。

使用預存的憑證簽章
以可選取清單的形式,顯示儲存在電腦憑證存放區內的數位憑證。

時間戳記 URI
顯示時間戳記服務的統一資源定位器 (URL),ClickOnce 會使用此 URL 來驗證憑證的時效。如需時間戳記的詳細資訊,請參閱 ClickOnce 部署和 Authenticode。

索引標籤和面板描述
使用 MageUI.exe 開啟文件時,文件會出現在自己的索引標籤頁內。每個索引標籤都包含一組屬性面板。面板中含有一組文件資料的子集。如需編輯每一類文件時可用之 UI 項目的詳細資訊,請參閱 MageUI.exe 部署資訊清單索引標籤和 MageUI.exe 應用程式資訊清單索引標籤。

請參閱
工作
逐步解說:手動部署 ClickOnce 應用程式

參考
資訊清單產生和編輯工具 (Mage.exe)

概念
ClickOnce 部署概觀

VS2005 與 VS2008 的相容性

<%@ Page Language="C#" AutoEventWireup="true" CodeBehind="WebForm1.aspx.cs" Inherits="t1.WebForm1" %>



VS2005 與 VS2008 的相容性


Vistual Studio 2008 正式版已經發佈,每次有新產品,最麻煩的就是和之前版本的相容性,尤其Visual Studio 至2005版開始,已經有Clirnt- Server(Foundation Server)的架構,這時相容性就更顯重要了,國外已經有位MVP Grant Holliday幫我們做了這樣的測試,請參考:http://ozgrant.com/2007/10/22/vsts-2005-2008-compatibility-matrix/


Products

VS 2005

VS 2008

TFS 2005

TFS 2008

Build 2005

Build 2008

TE 2005

TE 2008

Web Access

Power Tools

VS Addins

VS 2005

-

Yes. Note #1

Yes

Yes. Note #2, #3

Yes. V8.0 SLN files build.

Yes. Note #2, #3

Yes

Yes. Note #1

Yes

Yes

Yes

VS 2008

-

-

Yes. Note #4, #5

Yes

Yes. Note #5, #6

Yes

Yes. Note #1

Yes

No. Note #7

Partial. Note #8, #9

Partial. Note #8

TFS 2005

-

-

-

N/A

Yes

No

Yes

Yes

Yes

N/A

N/A

TFS 2008

-

-

-

-

No

Yes

Yes

Yes

Yes. Note #7

N/A

N/A

Build 2005

-

-

-

-

-

N/A

Yes

Yes. Note #5

Yes

N/A

N/A

Build 2008

-

-

-

-

-

-

Yes. Note #2, #3

Yes

Yes

N/A

N/A

TE 2005

-

-

-

-

-

-

-

Yes. Note #1

Yes

Yes

Yes

TE 2008

-

-

-

-

-

-

-

-

No. Note #7

Partial. Note #8, #9

Partial. Note #8

Web Access

-

-

-

-

-

-

-

-

-

N/A

N/A

Power Tools

-

-

-

-

-

-

-

-

-

-

N/A

VS Addins

-

-

-

-

-

-

-

-

-

-

-


 



Notes



Note #1

You can install VS2005 and VS2008 side-by-side on the same machine. (See Aaron’s
blog post below)

Note #2

For an VS2005 client to start a build on an Orcas server, the build definition
needs to be stored at $/<TeamProject>/TeamBuildTypes/<name>

Note #3

VS2005 will be able to start a build, but it can’t queue a build, see the list
of builds in the queue, see the list of build agents, etc.

Note #4

A VS2008 client will not be able to create a new build definition on a TFS2005
server. Workaround: You could branch an existing build type in
$/<TeamProject>/TeamBuildTypes/<name>

Note #5

When starting a build, a VS2008 client will not be able to change any parameters
in the dialog for a TFS2005 Server.

Note #6

A Team Build 2005 server does not understand a VS2008 Solution File. Workaround:
Changing the version number inside the SLN to Version 9.0. You will also need to
copy the MSBuild directory V8.0 directory to V9.0. This could be done
dynamically with a MSBuild task (See workaround below)

Note #7

Team System Web Access (TSWA) relies on the TFS2005 Object Model. You must have
Team Explorer 2005 installed on the server that has TSWA installed

Note #8

The current TFS Power Tools (inc. Checkin Policy Pack) are compiled against the
TFS2005 Object Model.  VS2008 doesn’t support loading both object models within
the same process, therefore any Power Tools or addins that get loaded in VS
either need to be recompiled against the TFS 2008 object model or policy needs
to be used to redirect references from the TFS 2005 assemblies to the TFS 2008
assemblies. (See Ed Hintz’s blog post below)

Note #9

Non-VS add-in Power Tools (everything except the Process Template Editor,
checkin policy pack and Annotate/TreeDiff) will work fine as long as the TFS
2005 Team Explorer is also installed.


3/18/2009

Ildasm.exe 教學

文章&圖示請參照http://msdn.microsoft.com/zh-tw/library/aa309387(VS.71).aspx

這個教學課程提供了 .NET Framework SDK 中所附之 MSIL 反組譯工具 (Ildasm.exe) 的簡介。Ildasm.exe 工具可以剖析任何 .NET Framework .exe 或 .dll 組件 (Assembly),並且以人們可閱讀的 (Human-Readable) 格式顯示資訊。Ildasm.exe 不只會顯示 Microsoft Intermediate Language (MSIL) 程式碼,也會顯示包括介面在內的命名空間 (Namespace) 和型別。您可以使用 Ildasm.exe 來檢查 .NET Framework 的原生組件 (例如 Mscorlib.dll),以及其他人提供的或是您自行建立的 .NET Framework 組件。大部分 .NET Framework 開發人員都會認為 Ildasm.exe 是不可或缺的工具。

對於這個教學課程,請使用隨附在 SDK 中之 WordCount 範例的 Visual C# 版本。您也可以使用 Visual Basic 版本,但是這兩種語言所產生的 MSIL 將會不同,畫面影像也不盡相同。WordCount 位於 \Samples\Applications\WordCount\ 目錄中。若要建置 (Build) 和執行範例,請依照 Readme.htm 檔案中所列的指示進行。這個教學課程會使用 Ildasm.exe 來檢查 WordCount.exe 組件。

若要開始,請建置 WordCount 範例,並使用下列命令列將它載入 Ildasm.exe 中:

ildasm WordCount.exe

這樣便會使 Ildasm.exe 的視窗顯示出來,如下圖所示。



Ildasm.exe 視窗中的樹狀結構會顯示 WordCount.exe 內部包含的組件資訊清單資訊,以及四個全域類別型別:App、ArgParser、WordCountArgParser 和 WordCounter。

按兩下樹狀結構中的任何型別,即可看見型別的詳細資訊。在下圖中,已將 WordCounter 類別型別展開。



在上圖中,您可以看見所有的 WordCounter 成員。下列表格將說明每一個圖形符號所代表的意義。

符號 意義
詳細資訊
命名空間
類別
介面
數值類別
列舉型別
方法
靜態方法
欄位
靜態欄位
事件
屬性
資訊清單或類別資訊項目

按兩下 .class public auto ansi beforefieldinit 項目會顯示下列資訊:



在上圖中,您可以清楚地看出來,WordCounter 型別是從 System.Object 型別衍生而來。

WordCounter 型別還包含另外一個型別,名稱為 WordOccurrence。您可以將 WordOccurrence 型別展開,即可看見它的成員,如下圖所示。



從樹狀結構中可以看出來,WordOccurrence 實作了 System.IComparable 介面,更明確地講,就是 CompareTo 方法。不過,在後續的說明中,我們將略過 WordOccurrence 型別,而將焦點集中在 WordCounter 型別上。

您可以看到 WordCounter 型別含有五個 private 欄位:totalBytes、totalChars、totalLines、totalWords 和 wordCounter。前四個欄位是 int64 型別的執行個體 (Instance),而 wordCounter 欄位則是 System.Collections.SortedList 型別的參考。

在這些欄位之後,您可以看見方法。第一個方法 .ctor 是建構函式 (Constructor)。這個特殊的型別只有一個建構函式,但是其他型別則可以有多個建構函式,每一個的簽名碼 (Signature) 都不同。WordCounter 建構函式的傳回型別 (Return Type) 為 void (和所有建構函式一樣),而且不接受參數。如果按兩下建構函式方法,會出現新的視窗,它會顯示方法中所包含的 MSIL 程式碼,如下圖所示。



MSIL 程式碼實際上很容易閱讀和了解 (如需所有的詳細資訊,請參閱位於 \Tool Developers Guide\Docs 資料夾 Partition III CIL.doc 檔案中的 CIL Instruction Set Specification)。在最接近頂端的地方,您可以看見這個建構函式需要 50 個位元組的 MSIL 程式碼。從這個數字並不能判斷出 JIT 編譯器將會發出多少機器碼,因為它的大小是根據主機 CPU 和用來產生程式碼的編譯器而定。

Common Language Runtime 為堆疊架構。因此,若要執行任何作業,MSIL 程式碼會先將運算元推入虛擬堆疊中,然後執行運算子。運算子會將運算元從堆疊中抓取出來、執行所需的作業,然後將結果放回堆疊上。不論任何時候,這個方法推入虛擬堆疊上的運算元都不能超過八個。您只要查看出現在 MSIL 程式碼前面的 .maxstack 屬性,就可以辨識出這個數目。

現在,請檢查前面幾個 MSIL 指令,如下列四行:

IL_0000: ldarg.0 ; Load the object's 'this' pointer on the stack
IL_0001: ldc.i4.0 ; Load the constant 4-byte value of 0 on the stack
IL_0002: conv.i8 ; Convert the 4-byte 0 to an 8-byte 0
IL_0003: stfld int64 WordCounter::totalLines

位於 IL_0000 的指令會將傳遞至方法的第一個參數載入到虛擬堆疊上,而且一定會將物件記憶體的位址傳遞給每一個執行個體方法 (Instance Method)。這個引數稱為 Argument Zero,而且不會明確顯示在方法的簽名碼中。因此,即使 .ctor 方法看起來像是接收了零個引數,實際上是接收了一個引數。接著,位於 IL_0000 的指令會將這個物件的指標載入到虛擬堆疊上。

位於 IL_0001 的指令會將 4 位元組的零值常數載入到虛擬堆疊上。

位於 IL_0002 的指令會取得堆疊頂端的數值 (4 位元組的零),並將它轉換成 8 位元組的零,如此便會將 8 位元組的零放到堆疊的頂端。

這時,堆疊含有兩個運算元:8 位元組的零和指向這個物件的指標。位於 IL_0003 的指令會使用這兩個運算元,將堆疊頂端的數值 (8 位元組的零) 儲存到堆疊上所辨識物件的 totalLines 欄位中。

totalChars、totalBytes 和 totalWords 欄位會重複相同的 MSIL 指令序列 (Sequence)。

wordCounter 欄位的初始化是從位於 IL_0020 的指令開始,如以下所示:

IL_0020: ldarg.0
IL_0021: newobj instance void [mscorlib]System.Collections.SortedList::.ctor()
IL_0026: stfld class [mscorlib]System.Collections.SortedList WordCounter::wordCounter

位於 IL_0020 的指令會將 WordCounter 的 this 指標推入虛擬堆疊上。newobj 指令不會使用這個運算元,但是位於 IL_0026 的 stfld 指令將會使用。

位於 IL_0021 的指令會告知 Runtime 建立新的 System.Collections.SortedList 物件,並且不使用任何引數呼叫它的建構函式。當 newobj 傳回時,SortedList 物件的位址是在堆疊上。這時候,位於 IL_0026 的 stfld 指令會將 SortedList 物件的指標儲存到 WordCounter 物件的 wordCounter 欄位中。

在所有 WordCounter 物件的欄位都完成初始化之後,位於 IL_002b 的指令會將 this 指標推到虛擬堆疊上,然後 IL_002b 會呼叫基底型別 (Base Type) (System.Object) 中的建構函式。

當然,位於 IL_0031 的最後一個指令是傳回指令,會使 WordCounter 建構函式傳回到建立函式的程式碼中。建構函式必須傳回 void,在建構函式傳回之前才不會將任何物件放入堆疊上。

下面是另外一個範例。請按兩下 GetWordsByOccurranceEnumerator 方法,即可看見它的 MSIL 程式碼,如下圖所示。



您可以看見,這個方法的程式碼大小為 69 個位元組,而且這個方法在虛擬堆疊上需要有四個位置。此外,這個方法還有三個區域變數:一個為 System.Collection.SortedList 型別,另外兩個為 System.Collections.IDictionaryEnumerator 型別。請注意,除非組件與 /debug 選項相容,否則不會將原始程式碼中提到的變數名稱發出到 MSIL 程式碼中。如果沒有使用 /debug,會分別使用 V_0、V_1 和 V_2 等變數名稱來取代 sl、de 和 CS$00000003$00000000。

當這個方法開始執行時,第一件事就是執行 newobj 指令,這個指令會建立新的 System.Collections.SortedList 物件,並呼叫這個物件的預設建構函式。當 newobj 傳回時,所建立物件的位址是在虛擬堆疊上。stloc.0 指令 (位於 IL_0005) 會將這個值儲存在區域變數 0 或 sl (不含 /debug 的 V_0) (屬於 System.Collections.SortedList 型別) 中。

位於 IL_0006 和 IL_0007 的指令會將 WordCounter 物件的 this 指標 (在傳遞至方法的 Argument Zero 中) 載入到堆疊上,並呼叫 GetWordsAlphabeticallyEnumerator 方法。當 call 指令傳回時,列舉值的位址是在堆疊上。stloc.1 指令 (位於 IL_000c) 會將這個位址儲存在區域變數 1 或 de (不含 /debug 的 V_1),這個變數屬於 System.Collections.IDictionaryEnumerator 型別。

位於 IL_000d 的 br.s 指令會造成 while 陳述式的 IL 測試條件無條件分支。這個 IL 測試條件從位於 IL_0032 的指令開始。在 IL_0032 位址中,會將 de (或 V_1) (IDictionaryEnumerator) 的位址推到堆疊上,然後在 IL_0033 位址呼叫它的 MoveNext 方法。如果 MoveNext 傳回 True,表示有要列舉的項目,而且 brtrue.s 指令會跳到位於 IL_000f 的指令。

在位於 IL_000f 和 IL_0010 的指令中,會將 sl (或 V_0) 和 de (或 V_1) 中的物件位址推到堆疊上。然後,呼叫 IdictionaryEnumerator 物件的 get_Value 屬性方法,以取得目前項目的項目數目。這個數目是儲存在 System.Int32 中的 32 位元值。程式碼會將 Int32 物件轉換成 int 數值型別 (Value Type)。將參考型別 (Reference Type) 轉換成數值型別需要位於 IL_0016 的 unbox 指令。當 unbox 傳回時,Unboxed 數值的位址是在堆疊上。ldind.i4 指令 (位於 IL_001b) 會將 4 位元組的數值 (這個數值會指向目前在堆疊上的位址) 載入到堆疊上。換句話說,Unboxed 4 位元組整數是放在堆疊上。

在位於 IL_001c 的指令中,會將 sl (或 V_1) 的數值 (IDictionaryEnumerator 的位址) 推到堆疊上,並呼叫它的 get_Key 屬性方法。當 get_Key 傳回時,System.Object 的位址是在堆疊上。程式碼知道字典中包含字串,因此編譯器會使用位於 IL_0022 的 castclass 指令,將這個 Object 轉換成 String。

以下幾個新的指令 (從 IL_0027 到 IL_002d) 會建立新的 WordOccurrence 物件,然後將物件的位址傳遞至 SortedLists 物件的 Add 方法。

在位於 IL_0032 的指令中,會再評估一次 while 陳述式的測試條件。如果 MoveNext 傳回 True,迴圈 (Loop) 會執行另一個循環。但是,如果 MoveNext 傳回 False,迴圈會停止執行,並在位於 IL_003a 的指令結束。位於 IL_003a 到 IL_0040 的指令會呼叫 SortLists 物件的 GetEnumerator 方法。傳回的值為 System.Collections.IDictionaryEnumerator,它是被留在堆疊上而成為 GetWordsByOccurrenceEnumerator 傳回值。