共用方式為


疑難排解程序 (Visual Basic)

本頁列出使用程序時可能發生的一些常見問題。

從函數程序傳回陣列類型

如果程序傳回陣列資料類型,則 Function 無法使用名稱將 Function 值儲存在陣列的元素中。 如果您嘗試這樣做,編譯器會將其解譯為對 .Function 下列範例會產生編譯器錯誤:

Function AllOnes(n As Integer) As Integer()
   For i As Integer = 1 To n - 1  
      ' The following statement generates a COMPILER ERROR.  
      AllOnes(i) = 1  
   Next  

   ' The following statement generates a COMPILER ERROR.  
   Return AllOnes()  
End Function

此陳述式AllOnes(i) = 1會產生編譯器錯誤,因為它似乎使用錯誤資料類型的引數 (純量Integer而不是Integer陣列) 進行呼叫AllOnes。 陳述式 Return AllOnes() 會產生編譯器錯誤,因為它似乎沒有引數來呼叫 AllOnes

正確做法: 若要能夠修改要傳回的陣列元素,請將內部陣列定義為局部變數。 下列範例編譯時沒有錯誤:

Function AllOnes(n As Integer) As Integer()
    Dim iArray(n - 1) As Integer
    For i = 0 To n - 1
        iArray(i) = 1
    Next
    Return iArray
End Function

程序呼叫未修改的引數

如果您想要允許程序變更呼叫程式碼中引數基礎的程式設計元素,則必須透過參考傳遞它。 但是,即使您依值傳遞參考類型引數,程序也可以存取它。

  • 基礎變數。 若要允許程序取代基礎變數元素本身的值,程序必須宣告參數 ByRef。 此外,呼叫程式碼不得將引數括在括弧中,因為這會覆寫 ByRef 傳遞機制。

  • 參考類型元素。 如果您宣告參數 ByVal,則程序無法修改基礎變數元素本身。 不過,如果引數是參考類型,則程序可以修改它所指向之物件的成員,即使它無法取代變數的值也一樣。 例如,如果引數是陣列變數,則程序無法為其指派新的陣列,但可以變更其一或多個元素。 變更的元素會反映在呼叫程式碼的基礎陣列變數中。

下列範例定義兩個程序,依值取得陣列變數,並對其元素進行操作。 程序 increase 只是將一個添加到每個元素中。 程序 replace 會將新陣列指派給參數 a() ,然後將一個新增至每個元素。 不過,重新指派不會影響呼叫程式碼中的基礎陣列變數,因為 a() 宣告了 ByVal

Public Sub increase(ByVal a() As Long)
    For j As Integer = 0 To UBound(a)
        a(j) = a(j) + 1
    Next j
End Sub
Public Sub replace(ByVal a() As Long)
    Dim k() As Long = {100, 200, 300}
    a = k
    For j As Integer = 0 To UBound(a)
        a(j) = a(j) + 1
    Next j
End Sub

下列範例會呼叫 increasereplace

Dim n() As Long = {10, 20, 30, 40}
Call increase(n)
MsgBox("After increase(n): " & CStr(n(0)) & ", " & 
    CStr(n(1)) & ", " & CStr(n(2)) & ", " & CStr(n(3)))
Call replace(n)
MsgBox("After replace(n): " & CStr(n(0)) & ", " & 
    CStr(n(1)) & ", " & CStr(n(2)) & ", " & CStr(n(3)))

第一個 MsgBox 呼叫顯示「增加後(n):11、21、31、41」。 因為 n 是參考類型, increase 可以變更其成員,即使已傳遞 ByVal

第二個 MsgBox 呼叫顯示「替換後(n):11、21、31、41」。 因為 傳遞了 ,所以n不能透過為變數指派一個新陣列來修改變數nreplaceByVal 當建立新的陣列實例k並將其指派給局部變數areplace,它會遺失呼叫程式碼傳入的參考n。 當它遞增 的 a成員時,只有本機陣列 k 受到影響。

正確做法: 若要能夠修改基礎變數元素本身,請透過引用傳遞它。 下列範例顯示宣 replace 告的變更,允許它在呼叫程式碼中將一個陣列取代為另一個陣列:

Public Sub replace(ByRef a() As Long)

無法定義多載

如果您想要定義程序的多載版本,則必須使用相同的名稱,但不同的簽章。 如果編譯器無法將您的宣告與具有相同簽章的多載區分開來,則會產生錯誤。

程序的 簽章 是由程序名稱及參數清單所決定。 每一個多載必須與所有其他多載具有相同的名稱,但必須在簽章的至少一個其他元件中與所有多載不同。 如需相關資訊,請參閱 程序多載

下列項目即使與參數清單相關,也不是程序簽章的元件:

  • 程序修飾詞關鍵字,例如 Public、 和 SharedStatic
  • 參數名稱。
  • 參數修飾詞關鍵字,例如 ByRefOptional
  • 傳回值的資料類型 (轉換運算子除外)。

您無法透過僅變更上述一個或多個項目來多載程序。

正確做法: 若要能夠定義程序多載,您必須變更簽章。 因為您必須使用相同的名稱,所以必須改變參數的數目、順序或資料類型。 在一般程序中,您可以變更類型參數的數目。 在轉換運算子 (CType 運算子) 中,您可以變更傳回類型。

使用 Optional 和 ParamArray 引數的重載解析

如果您要使用一或多個 選擇性 參數或 ParamArray 參數來多載程序,則必須避免複製任何 隱含多載。 如需相關資訊,請參閱 多載程序中的考量

呼叫錯誤版本的多載程序

如果程式有數個多載版本,您應該熟悉其所有參數清單,並瞭解 Visual Basic 如何解析多載之間的呼叫。 否則,您可以呼叫預期以外的多載。

當您決定要呼叫哪個多載時,請小心遵守下列規則:

  • 提供正確數量的引數,並以正確的順序。
  • 理想情況下,您的引數應該具有與相應參數完全相同的資料類型。 在任何情況下,每個引數的資料類型都必須擴大到其對應參數的資料類型。 即使將 Option Strict 陳述式 設定為 Off,也是如此。 如果多載需要從引數清單中進行任何縮小轉換,則該多載不符合呼叫資格。
  • 如果您提供需要加寬的引數,請使其資料類型盡可能接近對應的參數資料類型。 如果兩個或多個多載接受您的引數資料類型,編譯器會解析您對呼叫呼叫的多載,以呼叫最少的加寬量。

您可以在準備引數時使用 CType 函數 轉換關鍵字來減少資料類型不相符的機會。

過載解析失敗

當您呼叫多載的程序時,編譯器會嘗試消除除一個多載之外的所有多載。 如果成功,它會解析對該多載的呼叫。 如果它消除了所有多載,或者如果它無法將合格多載減少到單一候選,則會產生錯誤。

下列範例說明多載解決程式:

Overloads Sub z(ByVal x As Byte, ByVal y As Double)
End Sub
Overloads Sub z(ByVal x As Short, ByVal y As Single)
End Sub
Overloads Sub z(ByVal x As Integer, ByVal y As Single)
End Sub
Dim r, s As Short
Call z(r, s)
Dim p As Byte, q As Short
' The following statement causes an overload resolution error.
Call z(p, q)

在第一次呼叫中,編譯器會消除第一個多載,因為第一個引數 (Short) 的類型會縮小到對應參數 ()Byte 的類型。 然後,它會消除第三個多載,因為第二個多載 (ShortSingle) 中的每個引數類型都會擴大到第三個多載 (IntegerSingle) 中的對應類型。 第二個多載需要較少的加寬,因此編譯器會使用它進行呼叫。

在第二次呼叫中,編譯器無法根據縮小來消除任何多載。 它會消除第三個多載,原因與第一次呼叫相同,因為它可以呼叫第二個多載,且引數類型的擴寬較少。 不過,編譯器無法在第一個和第二個多載之間解析。 每個都有一個已定義的參數類型,該類型會加寬到另一個中的對應類型 (ByteShort,但 SingleDouble)。 因此,編譯器會產生多載解析錯誤。

正確做法: 若要能夠呼叫多載的程式而不會模明,請使用 CType 函式 將引數資料類型與參數類型相符。 下列範例顯示強制解析為第二個多載的呼叫 z

Call z(CType(p, Short), CType(q, Single))

使用 Optional 和 ParamArray 引數的重載解析

如果程式的兩個多載具有相同的簽章,但最後一個參數在其中一個參數中宣告為 Optional ,而在另一個參數中宣告 ParamArray ,編譯器會根據最接近的相符專案解析對該程式的呼叫。 如需詳細資訊,請參閱 多載解析

另請參閱