Share via


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

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

Devolver um tipo de matriz a partir de um procedimento de função

Se um Function procedimento devolver um tipo de dados de matriz, não pode utilizar o Function nome para armazenar valores nos elementos da matriz. Se tentar fazê-lo, o compilador interpreta-o como uma chamada para o Function. O exemplo seguinte 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 argumentos.

Abordagem correta: Para poder modificar os elementos de uma matriz que deve ser devolvida, defina uma matriz interna como uma variável local. O exemplo seguinte 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 pretender permitir que um procedimento altere um elemento de programação subjacente a um argumento no código de chamada, tem de passá-lo por referência. No entanto, um procedimento pode aceder aos elementos de um argumento de tipo de referência mesmo que o transmita por valor.

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

  • Elementos do tipo de referência. Se declarar um parâmetro ByVal, o procedimento não pode modificar o próprio elemento da variável subjacente. No entanto, se o argumento for um tipo de referência, o procedimento pode modificar os membros do objeto ao 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 pode atribuir uma nova matriz à mesma, mas pode alterar um ou mais dos respetivos elementos. Os elementos alterados refletem-se na variável de matriz subjacente no código de chamada.

O exemplo seguinte define dois procedimentos que assumem uma variável de matriz por valor e operam nos respetivos elementos. O procedimento increase adiciona simplesmente 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() é declarado 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 seguinte 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 apresenta "Após aumento(n): 11, 21, 31, 41". Uma n vez que é um tipo de referência, increase pode alterar os respetivos membros, mesmo que seja transmitido ByVal.

A segunda MsgBox chamada apresenta "Após substituir(n): 11, 21, 31, 41". Uma n vez que é transmitido ByVal, replace não é possível modificar a variável n ao atribuir-lhe uma nova matriz. Quando replace cria a nova instância k de matriz e a atribui à variável alocal, perde a referência a n transmitida pelo código de chamada. Quando incrementa os membros do a, apenas a matriz k local é afetada.

Abordagem correta: Para poder modificar um elemento variável subjacente, transmita-o por referência. O exemplo seguinte mostra a alteração na declaração de replace que lhe 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 quiser definir uma versão sobrecarregada de um procedimento, tem de utilizar o mesmo nome, mas uma assinatura diferente. Se o compilador não conseguir diferenciar a sua declaração de uma sobrecarga com a mesma assinatura, gera um erro.

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

Os seguintes itens, apesar de serem da lista de parâmetros, não são componentes da assinatura de um procedimento:

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

Não pode sobrecarregar um procedimento ao variar apenas um ou mais dos itens anteriores.

Abordagem correta: Para poder definir uma sobrecarga de procedimentos, tem de variar a assinatura. Uma vez que tem de utilizar o mesmo nome, tem de variar o número, a ordem ou os tipos de dados dos parâmetros. Num procedimento genérico, pode variar o número de parâmetros do tipo. Num operador de conversão (Função CType), pode variar o tipo de retorno.

Resolução de sobrecarga com argumentos Opcionais e ParamArray

Se estiver a sobrecarregar um procedimento com um ou mais parâmetros Opcionais ou um parâmetro ParamArray , tem de evitar duplicar qualquer uma das sobrecargas implícitas. Para obter informações, veja Considerações em Procedimentos de Sobrecarga.

Chamar a versão errada de um procedimento sobrecarregado

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

Quando tiver determinado a sobrecarga que pretende chamar, tenha cuidado ao observar as seguintes regras:

  • Forneça o número correto de argumentos e na ordem correta.
  • Idealmente, os 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 tem de ser alargado ao do parâmetro correspondente. Isto é verdade mesmo com a Instrução Estrita de Opção definida como Off. Se uma sobrecarga exigir qualquer conversão de restrição da sua lista de argumentos, essa sobrecarga não é elegível para ser chamada.
  • Se fornecer argumentos que exijam o alargamento, torne os respetivos tipos de dados o mais próximo possível dos tipos de dados de parâmetros correspondentes. Se duas ou mais sobrecargas aceitarem os tipos de dados de argumentos, o compilador resolve a chamada para a sobrecarga que exige a menor quantidade de alargamento.

Pode reduzir a probabilidade de incompatibilidades de tipos de dados ao utilizar a palavra-chave de conversão da Função CType ao preparar os seus argumentos.

Falha na resolução de sobrecarga

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

O exemplo seguinte 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) alarga para o tipo correspondente na terceira sobrecarga (Integer e Single). A segunda sobrecarga requer menos alargamento, pelo que o compilador a utiliza para a chamada.

Na segunda chamada, o compilador não pode eliminar nenhuma das sobrecargas com base no estreitamento. Elimina a terceira sobrecarga pela mesma razão que na primeira chamada, porque pode chamar a segunda sobrecarga com menos alargamento dos tipos de argumentos. No entanto, o compilador não consegue resolver entre a primeira e a segunda sobrecargas. Cada um tem um tipo de parâmetro definido que se alarga ao tipo correspondente no outro (Byte para Short, mas Single para Double). Por conseguinte, o compilador gera um erro de resolução de sobrecarga.

Abordagem correta: Para poder chamar um procedimento sobrecarregado sem ambiguidade, utilize a Função CType para corresponder os tipos de dados de argumentos aos tipos de parâmetros. O exemplo seguinte mostra uma chamada para que força a z resolução para a 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 se o último parâmetro for declarado Opcional numa e ParamArray na outra, o compilador resolverá uma chamada para esse procedimento de acordo com a correspondência mais próxima. Para obter mais informações, veja Resolução de Sobrecarga.

Ver também