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
Foi útil?

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
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top