Переключение Byref на Byval при вызовах методов VB.NET
Переключение Byref в Byval при вызове метода
Я получил много предупреждений из-за:
"Неявное преобразование из xxxx в yyyy при копировании значения параметра" ByRef "zzzz обратно в соответствующий аргумент".
Я чувствую, что было бы безопасно изменить параметры функции с byref на byval, поскольку ничего особенного не делается с указателями ссылочного типа внутри этих методов, просто используются ссылочные типы, и я думаю, что поведение будет точно таким же, если выполняется с копией указателя, а не оригинала.
Другое соображение заключается в том, что у меня есть два класса, которые наследуются от базового класса. Та же самая ситуация происходит в том, что параметры byref вызывают неявное приведение от базового класса к более узкому конкретному классу. Опять же, я не вижу никаких проблем с этим кодом, выполняющим byval.
У кого-нибудь есть советы по использованию параметров в функциях при работе с ссылочными типами?
Некоторые другие вещи, которые в настоящее время передаются byref в моем проекте, являются объектами соединения с базой данных, то есть OracleConnection и SqlConnection. Есть ли веская причина для их передачи?
Пример 1
Неявное преобразование из "Object" в "Integer" при копировании значения "ByRef" параметра "value" обратно в соответствующий аргумент.
Телефонный код:
cmd = New SqlCommand()
cmd.Parameters.Add(CreateParameter("Alpha", SqlDbType.Int,ParameterDirection.Input, -1, AlphaValue))
Функция:
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
Пример 2
Неявное преобразование из "System.Data.IDataReader" в "System.Data.SqlClient.SqlDataReader" при копировании значения параметра "ByRef" "reader" обратно в соответствующий аргумент.
Телефонный код:
Dim reader As new SqlDataReader
ReleaseReader(reader)
Метод:
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
1 ответ
При определении метода в VB.Net или C# в этом отношении вы должны передавать параметры по значению (ByVal), если вам не нужно использовать семантику ByRef. Если вы не сбрасываете значение параметра в методе, то определенно превратите их в вызовы ByVal.
Если вы сбрасываете ссылку, но не пользуетесь ею с сайта вызова, я бы написал вспомогательный метод, который принимает параметр ByVal и вызывает метод, принимающий ByRef. Это удалит предупреждение, потому что полученный код не будет подвержен сужающим ошибкам преобразования.
Например:
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