Share via


Risoluzione dei problemi relativi alle routine

Aggiornamento: novembre 2007

In questa pagina sono elencati alcuni problemi comuni che possono verificarsi durante l'utilizzo delle routine.

Restituzione di un tipo di matrice da una routine Function

Se una routine Function restituisce un tipo di dati matrice, non è possibile utilizzare il nome Function per memorizzare valori negli elementi della matrice. Se si tenta di effettuare questa operazione, il compilatore la interpreterà come una chiamata a Function. Nell'esempio riportato di seguito vengono generati errori del compilatore.

Function allOnes(ByVal n As Integer) As Integer()

For i As Integer = 1 To n - 1

' The following statement generates a COMPILER ERROR.

allOnes(i) = 1

Next i

' The following statement generates a COMPILER ERROR.

Return allOnes()

End Function

‎L'istruzione allOnes(i) = 1 genera un errore del compilatore poiché effettua una chiamata a allOnes utilizzando un argomento con tipo di dati errato (un valore Integer singleton anziché una matrice Integer). L'istruzione Return allOnes() genera un errore del compilatore poiché effettua una chiamata a allOnes senza argomenti.

Approccio corretto: per modificare gli elementi di una matrice che deve essere restituita, è necessario definire una matrice interna come variabile locale. Nell'esempio riportato di seguito la compilazione viene eseguita senza errori.

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

Argomento non modificato dalla chiamata di routine

Per consentire a una routine di modificare un elemento di programmazione sottostante a un argomento nel codice chiamante, è necessario passare tale elemento per riferimento. Tuttavia, una routine può accedere agli elementi di un argomento tipo di riferimento anche se vengono passati per valore.

  • Variabile sottostante. Per consentire alla routine di sostituire il valore dell'elemento variabile sottostante, è necessario che la routine dichiari il parametro ByRef. Inoltre, il codice chiamante non deve racchiudere l'argomento tra parentesi per evitare di eseguire l'override del meccanismo di passaggio ByRef.

  • Elementi del tipo di riferimento. Se si dichiara un parametro ByVal, la routine non può modificare l'elemento variabile sottostante. Tuttavia, se l'argomento è un tipo di riferimento, la routine può modificare i membri dell'oggetto ai quali punta, anche se non può sostituire il valore della variabile. Se ad esempio l'argomento è una variabile di matrice, la routine non può assegnare una nuova matrice all'argomento, ma può modificare uno o più elementi di quest'ultimo. Gli elementi modificati vengono riflessi nella variabile di matrice sottostante del codice chiamante.

Nell'esempio riportato di seguito vengono definite due routine che accettano una variabile di matrice per valore e operano sui relativi elementi. La routine increase aggiunge semplicemente uno a ogni elemento. La routine replace assegna una nuova matrice al parametro a(), quindi aggiunge uno a ogni elemento. Tuttavia, la riassegnazione non ha effetto sulla variabile di matrice sottostante del codice chiamante in quanto a() viene dichiarato 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

Nell'esempio riportato di seguito vengono effettuate chiamate a increase e replace.

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)))

Alla prima chiamata MsgBox viene visualizzato il seguente messaggio: "After increase(n): 11, 21, 31, 41". Poiché n è un tipo di riferimento, increase può modificarne i membri, anche se viene passato ByVal.

Alla seconda chiamata MsgBox viene visualizzato il seguente messaggio: "After replace(n): 11, 21, 31, 41". Poiché n viene passato ByVal, replace non può modificare la variabile n assegnando a quest'ultima una nuova matrice. Quando replace crea la nuova istanza di matrice k e la assegna alla variabile locale a, perde il riferimento alla variabile n passata dal codice chiamante. Quando incrementa i membri di a, viene influenzata solo la matrice locale k.

Approccio corretto: per modificare un elemento variabile sottostante, è necessario passarlo per riferimento. Nell'esempio riportato di seguito viene illustrata la modifica apportata alla dichiarazione di replace, che consente alla routine di sostituire una matrice con un'altra nel codice chiamante.

Public Sub replace(ByRef a() As Long)

Impossibile definire un overload

Se si desidera definire una versione di overload di una routine, è necessario utilizzare lo stesso nome con una firma differente. Se il compilatore non è in grado di distinguere la dichiarazione da un overload con la stessa firma, viene generato un errore.

La firma di una routine viene determinata dal nome della routine e dall'elenco dei parametri. Ogni overload deve avere lo stesso nome di tutti gli altri overload, ma almeno uno degli altri componenti della firma deve essere differente. Per ulteriori informazioni, vedere Overload della routine.

Di seguito sono riportati gli elementi che, sebbene siano inclusi nell'elenco dei parametri, non sono componenti della firma di una routine:

  • Parole chiave di modificatori di routine, ad esempio Public, Shared e Static

  • Nomi di parametri

  • Parole chiave di modificatori di parametro, ad esempio ByRef e Optional

  • Tipo di dati del valore restituito (ad eccezione di un operatore di conversione)

Non è possibile eseguire l'overload di una routine modificando solo uno o più elementi descritti in precedenza.

Approccio corretto: per definire l'overload di una routine, è necessario modificare la firma. Poiché è necessario utilizzare lo stesso nome, devono essere modificati il numero, l'ordine o i tipi di dati dei parametri. In una routine generica è possibile modificare il numero di parametri di tipo. In un operatore di conversione (Funzione CType) è possibile modificare il tipo restituito.

Risoluzione dell'overload mediante gli argomenti Optional e ParamArray

Se si esegue l'overload di una routine con uno o più parametri Optional (Visual Basic) o con un parametro ParamArray, è necessario evitare la duplicazione degli overload impliciti. Per informazioni, vedere Considerazioni sull'overload di routine.

Chiamata a una versione errata di una routine di overload

Se per una routine sono presenti diverse versioni di overload, è necessario acquisire familiarità con tutti i relativi elenchi di parametri e comprendere la modalità di risoluzione delle chiamate tra gli overload in Visual Basic, per evitare di chiamare un overload diverso da quello desiderato.

Dopo aver stabilito l'overload da chiamare, è consigliabile attenersi alle seguenti regole:

  • Specificare il numero e l'ordine corretto degli argomenti.

  • I tipi di dati degli argomenti dovrebbero essere identici a quelli dei parametri corrispondenti. In ogni caso, il tipo di dati di ciascun argomento deve essere convertito verso il tipo di dati più grande del parametro corrispondente, anche quando l'Istruzione Option Strict è impostata su Off. Se un overload richiede una conversione verso un tipo di dati più piccolo dall'elenco degli argomenti, non sarà possibile chiamare tale overload.

  • Se si specificano argomenti che richiedono una conversione verso un tipo di dati più grande, definire i relativi tipi di dati in modo che siano più simili possibile ai tipi di dati dei parametri corrispondenti. Se due o più overload accettano i tipi di dati degli argomenti, il compilatore risolverà la chiamata nell'overload che richiede l'ampliamento di dati minimo.

È possibile ridurre il rischio di mancata corrispondenza tra i tipi di dati utilizzando la parola chiave di conversione della Funzione CType durante la preparazione degli argomenti.

Errore di risoluzione dell'overload

Quando si chiama una routine di overload, il compilatore tenta di eliminare tutti gli overload eccetto uno. Se l'operazione riesce, la chiamata viene risolta in questo overload. Se vengono eliminati tutti gli overload o se non è possibile ridurre gli overload possibili a uno soltanto, viene generato un errore.

Nell'esempio riportato di seguito viene illustrato il processo di risoluzione dell'overload.

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)

Durante la prima chiamata il compilatore elimina il primo overload poiché il tipo del primo argomento (Short) esegue la conversione verso il tipo di dati più piccolo (Byte) del parametro corrispondente. Viene quindi eliminato il terzo overload poiché ogni tipo di argomento del secondo overload (Short e Single) esegue la conversione verso il tipo di dati più grande corrispondente del terzo overload (Integer e Single). Il secondo overload richiede un minore ampliamento dei dati e viene quindi utilizzato dal compilatore per la chiamata.

Durante la seconda chiamata il compilatore non è in grado di eliminare alcun overload in base al meccanismo della conversione verso un tipo di dati più piccolo. Viene eliminato il terzo overload per lo stesso motivo indicato nella prima chiamata, in quanto è possibile chiamare il secondo overload con un ampliamento minore dei tipi degli argomenti. Tuttavia, il compilatore non è in grado di scegliere tra il primo e il secondo overload. Ciascun overload dispone di un tipo di parametro definito che viene convertito verso il tipo più grande corrispondente nell'altro overload (Byte in Short e Single in Double). Il compilatore, di conseguenza, genera un errore di risoluzione dell'overload.

Approccio corretto: per chiamare una routine di overload senza generare ambiguità, è necessario utilizzare la Funzione CType per fare in modo che i tipi di dati degli argomenti corrispondano ai tipi dei parametri. Nell'esempio riportato di seguito viene illustrata una chiamata a z che forza la risoluzione nel secondo overload.

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

Risoluzione dell'overload mediante gli argomenti Optional e ParamArray

Se due overload di una routine hanno firme identiche ma l'ultimo parametro di uno di essi è dichiarato come Optional (Visual Basic) e l'altro come ParamArray, il compilatore risolve una chiamata a tale routine in base al grado di corrispondenza maggiore. Per ulteriori informazioni, vedere Risoluzione dell'overload.

Vedere anche

Concetti

Routine in Visual Basic

Routine Sub

Routine Function

Routine Property

Routine di operatore

Parametri e argomenti delle routine

Overload della routine

Considerazioni sull'overload di routine

Risoluzione dell'overload