標籤:style http tar color com get
使用內聯中繼語言(Inline IL)
內聯中繼語言(Inline IL)能夠直接在中繼語言(intermediate language,IL)中定義函數體,中繼語言是 F# 編譯後的語言,它主要為語言添加了實現特定低級運算子和函數,比如,加法和box 和 not 的功能。我們很少會用到這個功能,因為F# 庫FSharp.Core.dll 已經公開了所有的、可能需要的產生中繼語言的功能。然而,有一些極為罕見的情況,不能在 F# 中完成,而只能在中繼語言中實現,內聯中繼語言是很好的選擇。
使用內聯中繼語言很簡單,只要把中繼語言指令放在括弧和#號中間,(# #)。中繼語言指令放在字串中間,使用能夠被ilasm.exe 編譯的標準記號,它必須是正確的中繼語言形式,否則會編譯出錯;然後,傳遞參數給中繼語言指令,它們被壓入中繼語言評估棧(IL evaluation stack)中;還必須使用標準的冒號,告訴編譯器返回的類型是什麼,這要放在括弧中間;還需要顯式地指定參數類型,因為編譯器沒有辦法出它們的類型。
我們現在看一下使用內聯中繼語言的樣本。假設由於某種原因,我們要使用在 F# 基本庫fslib.dll 中定義的加法和減法運算子,用我們自己定義的函數去替換它們。我們定義了兩個函數add 和 sub,函數體使用中繼語言定義:
// declare add functionusing the IL add instruction
let add (x:int)(y:int) = (#"add"x y : int #)
// declare sub functionusing the IL sub instruction
let sub (x:int)(y:int) = (#"sub"x y : int #)
// test these functions
let x = add 1 1
let y = sub 4 2
// print the results
printfn "x: %i y:%i" x y
樣本的運行結果如下:
x: 2 y: 2
程式員應該小心使用這種方法,因為寫一個毫無意義的程式並不重要,編譯器不可能為此而發出警告。考慮下面的的程式,我們修改了一下前面的樣本,把 "add" 指令替換成 "ret" 指令,表示是返回值,在這個上下文中沒有意義。這個樣本在編譯時間沒有錯誤和警告,但是運行時會出錯。
// create a faulty add function
let add (x:int) (y:int) = (#"ret"x y : int #)
// attempt to use fault function
let x = add 1 1
樣本的運行結果如下:
Unhandled Exception: System.InvalidProgramException:Common Language Runtime
detected an invalid program.
at Error.add(Int32 x, Int32 y)
注意
隨.NET SDK 發布的一個工具能夠協助檢測這種錯誤,這個工具叫peverify.exe,更多有關這個工具的資訊,參見http://msdn2.microsoft.com/en-us/library/62bwd2yd(vs.80).aspx。