Переключение Byref на Byval при вызовах метода VB.NET
Вопрос
Переключение Byref на Byval при вызовах метода
У меня есть много предупреждений, поднятых из-за:
"Неявное преобразование из xxxx в гггг при копировании значения параметра 'ByRef' zzzz обратно в соответствующий аргумент".
Мне кажется, что было бы безопасно изменить параметры функции с byref на byval, поскольку ничего особенного с указателями ссылочного типа внутри этих методов не делается, ссылочные типы просто используются, и я думаю, что поведение было бы точно таким же, если бы выполнялось с копией указателя, а не оригинала.
Другое соображение заключается в том, что у меня есть два класса, которые наследуются от базового класса.Та же ситуация возникает в том, что параметры byref вызывают неявное приведение из базового класса в более узкий конкретный класс.Опять же, я также не вижу никаких проблем с этим кодом, запущенным byval.
Есть ли у кого-нибудь какие-либо советы относительно использования параметров в функциях при работе со ссылочными типами?
Некоторые из других вещей, которые в настоящее время передаются по ссылке ref в моем проекте, являются объектами подключения к базе данных, т. е.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
Решение
При определении метода в 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