2016-11-23 56 views
1

我仍然必須處理Visual Basic 6.爲什麼VB6在編譯時不檢查對象類型的對應關係?

我剛剛發現只有在運行時強制執行對象類型的對應關係。例如參見this question


我很震驚地發現這一點,我總是依靠對物體進行類型安全檢查。

有人知道這是否存在體系結構原因(這使得它至少是一個複雜的問題)?

如果涉及到多態性,我會理解它,但是當參數的類型是一個沒有被其他類實現的類時,我在編譯時就沒有發現類型檢查有問題...?

回答

4

歷史教訓

VB版本1至3是嚴格。類型一致性檢查仍然在運行時進行,但是它更嚴格。如果您將字符串分配給一個整數,則會出現運行時錯誤。我不知道爲什麼只在運行時進行一致性檢查 - 在猜測編譯時檢查很難實現。

在VB版本4語言已更改,以便(例如)將字符串分配給整數不會引發錯誤,但會隱式地將字符串值轉換爲整數。例如,如果字符串包含"0"""它將被轉換爲0。如果包含字符串,比如說"1E40",則會發生溢出錯誤。許多VB程序員(包括呃,我)都不喜歡這種變化,並稱之爲邪惡類型的強制。例如。大師Karl Peterson看到這個article

所以這個架構方法是「在猜測的時候嘗試在運行時轉換類型,只在不可能的時候引發錯誤」。這意味着,檢查在運行時。我想原則上編譯器可以檢測到對象類型是私有的,並且沒有被其他類實現的情況,並且在編譯時檢查,但我想這對編譯器開發者來說不是優先考慮的。開發人員甚至可能會弄糊塗瞭解爲什麼某些任務在運行時被檢查,而其他人則在編譯時被檢查。

在VB.Net中,默認行爲與VB6相同,以便升級遺留代碼。在VB.Net中優先採用Option Strict On,以便在編譯時進行檢查。編譯時檢查很有用,因爲它們可以及早標記錯誤。

+0

很有意思的答案,謝謝。 但對於正常(非對象)類型,對於例程調用的ByRef(默認)參數,**是在編譯時進行的! 現在我想到它可能大多是偶然的,因爲允許代碼的多個部分將相同變量視爲具有不同類型_might_可行,但會非常複雜和混亂。 – gbr

+0

是的,考慮到隱式強制的事情,並且提到完全沒有編譯時檢查(我沒有意識到),很可能靜態檢查在VB開發人員心目中並不是很多。 – gbr

+0

順便說一句,嘗試在VB 2010(與選擇嚴格關閉)我**做**得到一個編譯器錯誤,嘗試類似的問題,我提到的問題([expected-type-mismatch-error](https:/ /stackoverflow.com/questions/549357/expected-type-mismatch-error)),也許它只是在第一個.Net版本中丟失......? – gbr

2

只有接口被實現,而不是類。 VB6類Car隱式定義接口_Car,可以在任何外部項目(DLL)來實現,並且可以在組件類與任何其他接口(包括_Boat)捆綁

當你Dim c As Car它的界面_Car,這些會用來編譯器,所以c可以在任何對象上持有對_Car接口的引用,而不僅僅是Car類的實例。例如。你可以編寫一個實現了_Car_Boat接口的協調器Mix,所以Set c = New Mix編譯和運行,所以在Sail c接口的QI實際上成功(認爲「強制轉換」成功)。

請注意,這不是upcast也不是downcast,因爲_Car_Boat不受任何繼承形式的約束。但這是COM允許你通過IUnknown接口實現的。

在現代語言中,他們決定你總是需要在代碼中明確地向下轉換(否則會出現編譯錯誤),並且與「側投」(如在設計的汽車/船例子中一樣)你自己在腿上。

+0

我對最近的回覆表示歉意,我起初花了幾天的時間來看看你提出的,後來幾乎沒有時間。 (1/6) – gbr

+0

你提出了一些很好的觀點。 我不認爲我意識到「混合到船」的情景是可能的。我明白這是由於支持COM,但它似乎很瘋狂!但也許這只是VB語法在類和接口之間的混淆。因此,「As」總是指向接口,並且對象不會被轉換爲任何東西,它們總是保持所有的接口包,而不管來自您正在查看的「接口窗口」(變量/參數)。 在試圖變得聰明的VB做了一個大混亂,在我看來。 (2/6) – gbr

+0

我沒有考慮到一個鏈接的外部組件可能會實現項目的一個類。這隻會發生在ActiveX項目的非私有類中,對吧? (3/6) – gbr

相關問題