Procédures de résolution des problèmes (Visual Basic)

Cette page répertorie certains problèmes courants qui peuvent se produire lors de l’utilisation de procédures.

Retour d’un type de tableau à partir d’une procédure de fonction

Si une procédure Function retourne un type de données de tableau, vous ne pouvez pas utiliser le nom Function pour stocker des valeurs dans les éléments du tableau. Si vous tentez de le faire, le compilateur l’interprète comme un appel à l' Function. L’exemple suivant génère des erreurs de compilateur :

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

L’instruction AllOnes(i) = 1 génère une erreur du compilateur, car elle semble appeler AllOnes avec un argument du type de données incorrect (un Integer scalaire au lieu d’un tableau Integer ). L’instruction Return AllOnes() génère une erreur du compilateur, car elle semble appeler AllOnes sans argument.

Approche correcte : Pour pouvoir modifier les éléments d’un tableau à renvoyer, définissez un tableau interne en tant que variable locale. L’exemple suivant compile sans erreur :

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

Argument non modifié par appel de procédure

Si vous envisagez d’autoriser une procédure à modifier un élément de programmation sous-jacent à un argument dans le code appelant, vous devez le transmettre par référence. Toutefois, une procédure peut accéder aux éléments d’un argument de type référence même si vous la transmettez par valeur.

  • variable sous-jacente. Pour permettre à la procédure de remplacer la valeur de l’élément variable sous-jacent lui-même, la procédure doit déclarer le paramètre ByRef. En outre, le code appelant ne doit pas placer l’argument entre parenthèses, car cela remplacerait le mécanisme de passage de ByRef .

  • éléments de type Référence. Si vous déclarez un paramètre ByVal, la procédure ne peut pas modifier l’élément de variable sous-jacent lui-même. Toutefois, si l’argument est un type référence, la procédure peut modifier les membres de l’objet vers lequel il pointe, même s’il ne peut pas remplacer la valeur de la variable. Par exemple, si l’argument est une variable de tableau, la procédure ne peut pas lui affecter un nouveau tableau, mais elle peut modifier un ou plusieurs de ses éléments. Les éléments modifiés sont reflétés dans la variable de tableau sous-jacente dans le code appelant.

L’exemple suivant définit deux procédures qui prennent une variable de tableau par valeur et fonctionnent sur ses éléments. La procédure increase ajoute simplement un élément à chaque élément. La procédure replace affecte un nouveau tableau au paramètre a() , puis en ajoute un à chaque élément. Toutefois, la réaffectation n’affecte pas la variable de tableau sous-jacente dans le code appelant, car a() est déclaré 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

L’exemple suivant effectue des appels à increase et 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)))

Le premier appel MsgBox affiche « After increase(n): 11, 21, 31, 41 ». Étant donné que n est un type de référence, increase pouvez modifier ses membres, même s’il est passé ByVal.

Le deuxième appel MsgBox affiche « After replace(n) : 11, 21, 31, 41 ». Étant donné que n est passé ByVal, replace ne peut pas modifier la variable n en lui affectant un nouveau tableau. Lorsque replace crée la nouvelle instance de tableau k et l’affecte à la variable locale a, elle perd la référence à n passée par le code appelant. Lorsqu’il incrémente les membres de a, seul le tableau local k est affecté.

Approche correcte : Pour pouvoir modifier un élément de variable sous-jacent lui-même, transmettez-le par référence. L’exemple suivant montre la modification de la déclaration de replace qui lui permet de remplacer un tableau par un autre dans le code appelant :

Public Sub replace(ByRef a() As Long)

Impossible de définir une surcharge

Si vous souhaitez définir une version surchargée d’une procédure, vous devez utiliser le même nom, mais une signature différente. Si le compilateur ne peut pas différencier votre déclaration d’une surcharge avec la même signature, elle génère une erreur.

La signature d’une procédure est déterminée par le nom de la procédure et la liste des paramètres. Chaque surcharge doit avoir le même nom que toutes les autres surcharges, mais doit différer de toutes ces surcharges dans au moins l’un des autres composants de la signature. Pour plus d'informations, consultez Procedure Overloading.

Les éléments suivants, même s’ils se rapportent à la liste des paramètres, ne sont pas des composants de la signature d’une procédure :

  • Mots clés de modificateur de procédure, tels que Public, Sharedet Static.
  • Noms de paramètres.
  • Mots clés de modificateur de paramètres, tels que ByRef et Optional.
  • Type de données de la valeur de retour (à l’exception d’un opérateur de conversion).

Vous ne pouvez pas surcharger une procédure en variant un ou plusieurs des éléments précédents.

Approche correcte : Pour pouvoir définir une surcharge de procédure, vous devez varier la signature. Étant donné que vous devez utiliser le même nom, vous devez varier le nombre, l’ordre ou les types de données des paramètres. Dans une procédure générique, vous pouvez varier le nombre de paramètres de type. Dans un opérateur de conversion (fonction CType), vous pouvez varier le type de retour.

Résolution de surcharge avec des arguments Facultatifs et ParamArray

Si vous surchargez une procédure avec un ou plusieurs paramètres facultatifs ou un paramètre ParamArray , vous devez éviter de dupliquer l’une des surcharges implicites. Pour plus d’informations, consultez Considérations relatives aux procédures surchargées.

Appel de la version incorrecte d’une procédure surchargée

Si une procédure comporte plusieurs versions surchargées, vous devez être familiarisé avec toutes leurs listes de paramètres et comprendre comment Visual Basic résout les appels entre les surcharges. Sinon, vous pouvez appeler une surcharge autre que celle prévue.

Lorsque vous avez déterminé la surcharge que vous souhaitez appeler, veillez à observer les règles suivantes :

  • Indiquez le nombre correct d’arguments et dans l’ordre correct.
  • Dans l’idéal, vos arguments doivent avoir exactement les mêmes types de données que les paramètres correspondants. Dans tous les cas, le type de données de chaque argument doit s’élargir à celui de son paramètre correspondant. Cela est vrai même avec l’instruction Option Strict définie sur Off. Si une surcharge nécessite une conversion étroite de votre liste d’arguments, cette surcharge n’est pas éligible à l’appel.
  • Si vous fournissez des arguments qui nécessitent un élargissement, rendez leurs types de données aussi proches que possible des types de données de paramètre correspondants. Si deux surcharges ou plus acceptent vos types de données d’argument, le compilateur résout votre appel à la surcharge qui appelle le moins de quantité d’élargissement.

Vous pouvez réduire le risque d’incompatibilités de type de données à l’aide du mot clé de conversion fonction CType lors de la préparation de vos arguments.

Échec de la résolution de surcharge

Lorsque vous appelez une procédure surchargée, le compilateur tente d’éliminer toutes les surcharges, mais l’une des surcharges. Si elle réussit, elle résout l’appel à cette surcharge. S’il élimine toutes les surcharges ou s’il ne peut pas réduire les surcharges éligibles à un candidat unique, il génère une erreur.

L’exemple suivant illustre le processus de résolution de surcharge :

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)

Dans le premier appel, le compilateur élimine la première surcharge, car le type du premier argument (Short) se limite au type du paramètre correspondant (Byte). Il élimine ensuite la troisième surcharge, car chaque type d’argument dans la deuxième surcharge (Short et Single) s’étend sur le type correspondant dans la troisième surcharge (Integer et Single). La deuxième surcharge nécessite moins d’élargissement, de sorte que le compilateur l’utilise pour l’appel.

Dans le deuxième appel, le compilateur ne peut pas éliminer les surcharges sur la base d’un rétrécissement. Il élimine la troisième surcharge pour la même raison que dans le premier appel, car elle peut appeler la deuxième surcharge avec moins d’élargissement des types d’arguments. Toutefois, le compilateur ne peut pas résoudre entre les premières et deuxième surcharges. Chacun a un type de paramètre défini qui s’élargit au type correspondant dans l’autre (Byte à Short, mais Single à Double). Le compilateur génère donc une erreur de résolution de surcharge.

Approche correcte : Pour pouvoir appeler une procédure surchargée sans ambiguïté, utilisez fonction CType pour faire correspondre les types de données d’argument aux types de paramètres. L’exemple suivant montre un appel à z qui force la résolution à la deuxième surcharge.

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

Résolution de surcharge avec des arguments Facultatifs et ParamArray

Si deux surcharges d’une procédure ont des signatures identiques, sauf que le dernier paramètre est déclaré Facultatif dans l’un et ParamArray dans l’autre, le compilateur résout un appel à cette procédure en fonction de la correspondance la plus proche. Pour plus d'informations, consultez Overload Resolution.

Voir aussi