Partilhar via


Procedimentos de solução de problemas (Visual Basic)

Esta página lista alguns problemas comuns que podem ocorrer ao trabalhar com procedimentos.

Retornando um tipo de matriz de um procedimento de função

Se um Function procedimento retornar um tipo de dados de matriz, você não poderá usar o Function nome para armazenar valores nos elementos da matriz. Se você tentar fazer isso, o compilador interpretará como uma chamada para o Function. O exemplo a seguir gera erros do compilador:

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

A instrução AllOnes(i) = 1 gera um erro de compilador porque parece chamar AllOnes com um argumento do tipo de dados errado (um escalar Integer em vez de uma Integer matriz). A instrução Return AllOnes() gera um erro de compilador porque parece chamar AllOnes sem argumento.

Abordagem correta: Para poder modificar os elementos de uma matriz que deve ser retornada, defina uma matriz interna como uma variável local. O exemplo a seguir compila sem erro:

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

Argumento não modificado por chamada de procedimento

Se você pretende permitir que um procedimento altere um elemento de programação subjacente a um argumento no código de chamada, você deve passá-lo por referência. Mas um procedimento pode acessar os elementos de um argumento de tipo de referência mesmo se você passá-lo por valor.

  • Variável subjacente. Para permitir que o procedimento substitua o valor do próprio elemento variável subjacente, o procedimento deve declarar o parâmetro ByRef. Além disso, o código de chamada não deve colocar o argumento entre parênteses, porque isso substituiria o mecanismo de ByRef passagem.

  • Elementos de tipo de referência. Se você declarar um parâmetro ByVal, o procedimento não poderá modificar o próprio elemento variável subjacente. No entanto, se o argumento for um tipo de referência, o procedimento pode modificar os membros do objeto para o qual aponta, mesmo que não possa substituir o valor da variável. Por exemplo, se o argumento for uma variável de matriz, o procedimento não poderá atribuir uma nova matriz a ela, mas poderá alterar um ou mais de seus elementos. Os elementos alterados são refletidos na variável de matriz subjacente no código de chamada.

O exemplo a seguir define dois procedimentos que tomam uma variável de matriz por valor e operam em seus elementos. O procedimento increase simplesmente adiciona um a cada elemento. O procedimento replace atribui uma nova matriz ao parâmetro a() e, em seguida, adiciona uma a cada elemento. No entanto, a reatribuição não afeta a variável de matriz subjacente no código de chamada porque a() é declarada 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

O exemplo a seguir faz chamadas para 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)))

A primeira MsgBox chamada exibe "Após aumento(n): 11, 21, 31, 41". Por n ser um tipo de referência, increase pode alterar seus membros, mesmo que seja passado ByVal.

A segunda MsgBox chamada exibe "Após substituição(n): 11, 21, 31, 41". Como n é passado , replace não é possível ByValmodificar a variável n atribuindo uma nova matriz a ela. Quando replace cria a nova instância k de matriz e a atribui à variável alocal, ela perde a referência a n ser transmitida pelo código de chamada. Quando ele incrementa os membros do a, somente a matriz k local é afetada.

Abordagem correta: Para poder modificar um elemento variável subjacente em si, passe-o por referência. O exemplo a seguir mostra a alteração na declaração de que permite substituir uma matriz por outra no código de replace chamada:

Public Sub replace(ByRef a() As Long)

Não é possível definir uma sobrecarga

Se quiser definir uma versão sobrecarregada de um procedimento, você deve usar o mesmo nome, mas uma assinatura diferente. Se o compilador não puder diferenciar sua declaração de uma sobrecarga com a mesma assinatura, isso gerará um erro.

A assinatura de um procedimento é determinada pelo nome do procedimento e pela lista de parâmetros. Cada sobrecarga deve ter o mesmo nome que todas as outras sobrecargas, mas deve diferir de todas elas em pelo menos um dos outros componentes da assinatura. Para obter mais informações, consulte Sobrecarga de procedimento.

Os seguintes itens, embora pertençam à lista de parâmetros, não são componentes da assinatura de um procedimento:

  • Palavras-chave modificadoras de procedimento, como Public, Sharede Static.
  • Nomes de parâmetros.
  • Palavras-chave modificadoras de parâmetros, como ByRef e Optional.
  • O tipo de dados do valor de retorno (exceto para um operador de conversão).

Não é possível sobrecarregar um procedimento variando apenas um ou mais dos itens anteriores.

Abordagem correta: Para poder definir uma sobrecarga de procedimento, você deve variar a assinatura. Como você deve usar o mesmo nome, você deve variar o número, a ordem ou os tipos de dados dos parâmetros. Em um procedimento genérico, você pode variar o número de parâmetros de tipo. Em um operador de conversão (Operador CType), você pode variar o tipo de retorno.

Resolução de sobrecarga com argumentos Optional e ParamArray

Se você estiver sobrecarregando um procedimento com um ou mais parâmetros opcionais ou um parâmetro ParamArray , você deve evitar a duplicação de qualquer uma das sobrecargas implícitas. Para obter informações, consulte Considerações sobre procedimentos de sobrecarga.

Chamar a versão errada de um procedimento sobrecarregado

Se um procedimento tiver várias versões sobrecarregadas, você deve estar familiarizado com todas as suas listas de parâmetros e entender como o Visual Basic resolve chamadas entre as sobrecargas. Caso contrário, você pode chamar uma sobrecarga diferente da pretendida.

Quando tiver determinado qual sobrecarga deseja chamar, tenha cuidado para observar as seguintes regras:

  • Forneça o número correto de argumentos e na ordem correta.
  • Idealmente, seus argumentos devem ter exatamente os mesmos tipos de dados que os parâmetros correspondentes. Em qualquer caso, o tipo de dados de cada argumento deve ser ampliado para o de seu parâmetro correspondente. Isso é verdade mesmo com a Declaração Rígida de Opção definida como Off. Se uma sobrecarga exigir qualquer conversão restrita da sua lista de argumentos, essa sobrecarga não será qualificada para ser chamada.
  • Se você fornecer argumentos que exijam ampliação, torne seus tipos de dados o mais próximos possível dos tipos de dados de parâmetro correspondentes. Se duas ou mais sobrecargas aceitarem seus tipos de dados de argumento, o compilador resolverá sua chamada para a sobrecarga que exige a menor quantidade de ampliação.

Você pode reduzir a chance de incompatibilidades de tipo de dados usando a palavra-chave de conversão CType Function ao preparar seus argumentos.

Falha na resolução de sobrecarga

Quando você chama um procedimento sobrecarregado, o compilador tenta eliminar todas, exceto uma, das sobrecargas. Se for bem-sucedido, ele resolve a chamada para essa sobrecarga. Se eliminar todas as sobrecargas, ou se não puder reduzir as sobrecargas elegíveis a um único candidato, gera um erro.

O exemplo a seguir ilustra o processo de resolução de sobrecarga:

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)

Na primeira chamada, o compilador elimina a primeira sobrecarga porque o tipo do primeiro argumento (Short) se estreita para o tipo do parâmetro correspondente (Byte). Em seguida, elimina a terceira sobrecarga porque cada tipo de argumento na segunda sobrecarga (Short e Single) se amplia para o tipo correspondente na terceira sobrecarga (Integer e Single). A segunda sobrecarga requer menos ampliação, então o compilador a usa para a chamada.

Na segunda chamada, o compilador não pode eliminar nenhuma das sobrecargas com base no estreitamento. Ele elimina a terceira sobrecarga pelo mesmo motivo da primeira chamada, porque pode chamar a segunda sobrecarga com menos ampliação dos tipos de argumento. No entanto, o compilador não pode resolver entre a primeira e a segunda sobrecargas. Cada um tem um tipo de parâmetro definido que se alarga para o tipo correspondente no outro (Byte a Short, mas Single a Double). O compilador, portanto, gera um erro de resolução de sobrecarga.

Abordagem correta: Para poder chamar um procedimento sobrecarregado sem ambiguidade, use a função CType para corresponder os tipos de dados de argumento aos tipos de parâmetro. O exemplo a seguir mostra uma chamada para z que força a resolução para a segunda sobrecarga.

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

Resolução de sobrecarga com argumentos Optional e ParamArray

Se duas sobrecargas de um procedimento tiverem assinaturas idênticas, exceto que o último parâmetro é declarado Optional em um e ParamArray no outro, o compilador resolve uma chamada para esse procedimento de acordo com a correspondência mais próxima. Para obter mais informações, consulte Resolução de sobrecarga.

Consulte também