vb.netbyrefbyval

Switching Byref to Byval on method calls VB.NET


Switching Byref to Byval on method calls

I have many warnings raised due to:

"Implicit conversion from xxxx to yyyy in copying the value of 'ByRef' parameter zzzz back to the matching argument."

My feeling is that it would be safe to change the function parameters from byref to byval as nothing special is being done with the reference type pointers inside these methods the reference types are simply being used and I think the behaviour would be exactly the same if running with a copy a pointer rather than the original.

Another consideration is that I have two classes which inherit from a base class. The same situation is occuring in that the byref params are causing implicit casting from the base class to the narrower concrete class. Again I can't see any problems with this code running byval either.

Does anyone have any tips regarding use of parameters in functions when dealing with reference types?

Some of the other things that are currently being passed around byref in my project are database connection objects i.e. OracleConnection and SqlConnection. Is there any good reason for passing these around byref?

Example 1

Implicit conversion from 'Object' to 'Integer' in copying the value of 'ByRef' parameter 'value' back to the matching argument.

Calling code:

cmd = New SqlCommand()

cmd.Parameters.Add(CreateParameter("Alpha", SqlDbType.Int,ParameterDirection.Input, -1, AlphaValue))

Function:

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

Example 2

Implicit conversion from 'System.Data.IDataReader' to 'System.Data.SqlClient.SqlDataReader' in copying the value of 'ByRef' parameter 'reader' back to the matching argument.

Calling code:

Dim reader As new SqlDataReader

ReleaseReader(reader)

Method:

    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

Solution

  • When defining a method in VB.Net, or C# for that matter, the you should pass parameters by value (ByVal) unless you need to take advantage of ByRef semantics. If you are not resetting the parameter value within the method then you should definitely turn these into ByVal calls.

    If you are resetting the reference but not taking advantage of it from the call site then I would write a helper method which takes the parameter ByVal and calls into the one taking it ByRef. This will remove the warning because the resulting code won't be subject to narrowing conversion errors.

    For example:

    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