Compartilhar 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 o interpretará como uma chamada para .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 do 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 do compilador porque parece chamar AllOnes sem nenhum 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 é compilado sem erros:

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 de 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, pois isso substituiria o ByRef mecanismo de passagem.

  • Elementos de tipo de referência. Se você declarar um parâmetro ByVal, o procedimento não poderá modificar o próprio elemento de variável subjacente. No entanto, se o argumento for um tipo de referência, o procedimento poderá modificar os membros do objeto para o qual ele aponta, mesmo que ele 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 ele, 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 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 paraincrease: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 o aumento(n): 11, 21, 31, 41". Como n é um tipo de referência, increase pode alterar seus membros, mesmo que seja passado ByVal.

A segunda MsgBox chamada exibe "Após substituir(n): 11, 21, 31, 41". Como n é passado ByVal, replace não é possível modificar 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 passada pelo código de chamada. Quando incrementa os membros, asomente a matriz k local é afetada.

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

Public Sub replace(ByRef a() As Long)

Não é possível definir uma sobrecarga

Se você quiser definir uma versão sobrecarregada de um procedimento, deverá 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, ele 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 de todas as outras sobrecargas, mas deve ser diferente 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 sejam pertencentes à lista de parâmetros, não são componentes da assinatura de um procedimento:

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

Você não pode 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 Opcionais e ParamArray

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

Chamando a versão errada de um procedimento sobrecarregado

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

Quando você 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. De qualquer forma, o tipo de dados de cada argumento deve ser ampliado para o de seu parâmetro correspondente. Isso é verdadeiro mesmo com a instrução Option Strict definida como Off. Se uma sobrecarga exigir qualquer conversão de restrição da sua lista de argumentos, essa sobrecarga não será qualificada para ser chamada.
  • Se você fornecer argumentos que exigem ampliação, faça com que seus tipos de dados sejam o mais próximos possível dos tipos de dados de parâmetro correspondentes. Se duas ou mais sobrecargas aceitarem os 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 da Função CType 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 resolverá a chamada para essa sobrecarga. Se eliminar todas as sobrecargas ou se não puder reduzir as sobrecargas qualificadas para um único candidato, isso gerará 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 restringe ao tipo do parâmetro correspondente (Byte). Em seguida, elimina a terceira sobrecarga porque cada tipo de argumento na segunda sobrecarga (Short e Single) aumenta para o tipo correspondente na terceira sobrecarga (Integer e Single). A segunda sobrecarga requer menos ampliação, portanto, o compilador a usa para a chamada.

Na segunda chamada, o compilador não pode eliminar nenhuma das sobrecargas com base na restrição. Elimina a terceira sobrecarga pelo mesmo motivo da primeira chamada, pois 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 é ampliado para o tipo correspondente no outro (Byte para Short, mas Single para Double). Portanto, o compilador 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 que z força a resolução à segunda sobrecarga.

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

Resolução de sobrecarga com argumentos Opcionais e ParamArray

Se duas sobrecargas de um procedimento tiverem assinaturas idênticas, exceto que o último parâmetro será declarado opcional em um e ParamArray no outro, o compilador resolverá 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