Mudando Byref para Byval em chamadas de método VB.NET
Pergunta
Mudando Byref para Byval em chamadas de método
Tenho muitos avisos levantados devido a:
"Conversão implícita de xxxx para yyyy ao copiar o valor do parâmetro 'ByRef' zzzz de volta para o argumento correspondente."
Minha sensação é que seria seguro alterar os parâmetros da função de byref para byval, já que nada de especial está sendo feito com os ponteiros de tipo de referência dentro desses métodos, os tipos de referência estão simplesmente sendo usados e acho que o comportamento seria exatamente o mesmo se estiver executando com uma cópia, um ponteiro em vez do original.
Outra consideração é que tenho duas classes que herdam de uma classe base.A mesma situação está ocorrendo porque os parâmetros byref estão causando conversão implícita da classe base para a classe concreta mais estreita.Novamente, também não consigo ver nenhum problema com este código executando byval.
Alguém tem alguma dica sobre o uso de parâmetros em funções ao lidar com tipos de referência?
Algumas das outras coisas que estão sendo transmitidas atualmente por byref em meu projeto são objetos de conexão de banco de dados, ou seja,OracleConnection e SqlConnection.Existe alguma boa razão para distribuí-los por ref?
Exemplo 1
Conversão implícita de 'Object' para 'Integer' ao copiar o valor do parâmetro 'ByRef' 'value' de volta para o argumento correspondente.
Código de chamada:
cmd = New SqlCommand()
cmd.Parameters.Add(CreateParameter("Alpha", SqlDbType.Int,ParameterDirection.Input, -1, AlphaValue))
Função:
Private Function CreateParameter(ByVal parameterName As String, ByVal dbType As SqlDbType, ByVal direction As ParameterDirection, ByVal size As Integer, ByRef value As Object) As SqlParameter
Dim retParam As SqlParameter
retParam = New SqlParameter(parameterName, dbType)
retParam.Direction = direction
retParam.Size = size
retParam.Value = value
Return retParam
End Function
Exemplo 2
Conversão implícita de 'System.Data.IDataReader' para 'System.Data.SqlClient.SqlDataReader' na cópia do valor do parâmetro 'ByRef' 'reader' de volta para o argumento correspondente.
Código de chamada:
Dim reader As new SqlDataReader
ReleaseReader(reader)
Método:
Public Sub ReleaseReader(ByRef reader As IDataReader)
If reader IsNot Nothing Then
If Not reader.IsClosed Then
reader.Close()
End If
reader.Dispose()
End If
End Sub
Solução
Ao definir um método em VB.Net ou C#, você deve passar parâmetros por valor (ByVal), a menos que precise aproveitar as vantagens da semântica ByRef.Se você não estiver redefinindo o valor do parâmetro dentro do método, transforme-os definitivamente em chamadas ByVal.
Se você estiver redefinindo a referência, mas não aproveitando-a no site de chamada, eu escreveria um método auxiliar que pega o parâmetro ByVal e chama aquele que o usa ByRef.Isso removerá o aviso porque o código resultante não estará sujeito a erros de conversão restritivos.
Por exemplo:
Public Sub ExampleMethod(ByRef p1 As Object)
p1 = "foo"
End Sub
Public Sub ExampleMethodWrapper(ByVal p1 as Object)
ExampleMethod(p1)
End Sub
Public Sub Test()
Dim v1 As String = "hello"
Dim v2 As String = "world"
ExampleMethod(v1) ' Warning generated
ExampleMethodWrapper(v2) ' No warning
End Sub