Вопрос

Что следует учитывать при выборе между ByRef и ByVal.

Я понимаю разницу между ними, но не до конца понимаю, экономит ли ByRef ресурсы или нам вообще нужно об этом беспокоиться в среде .Net.

Как вы выбираете между ними, если функциональность не имеет значения в ситуации?

Это было полезно?

Решение

Об этом много дезинформации. Главное, что вы понимаете разницу между типами значений и ссылочными типами , а также разница между передачей по значению и передачей по ссылке .

Вы почти всегда хотите передать по значению. Передача по ссылке почти всегда для " я хочу вернуть более одного результата, а не просто путем добавления элементов в список, который передается. & Quot; Классическим примером метода, использующего передачу по ссылке, является Int32.TryParse где возвращаемое значение является успехом / неудачей, а проанализированное значение является «возвращенным» по выходному параметру.

Другие советы

По умолчанию для ВСЕХ типов используется значение byValue, но важно понимать, что эти два параметра означают для «ссылочного типа» (класса), а не для типа значения.(структуры).

Для ссылочного типа, если вы объявляете переменную ссылочного типа в методе, эта переменная является ячейкой памяти в кадре стека метода.Это не в куче.Когда вы инициализируете эту переменную (используя new или фабрику, что угодно), вы создаете реальный объект в куче, и адрес этого объекта сохраняется в объявленной ссылочной переменной в кадре стека ваших методов.

Когда вы передаете ссылочный тип другому методу с помощьюVal, вы создаете копию адреса, хранящегося в стеке вызывающих методов, и передаете копию этого значения (адрес указателя) вызываемому методу, где оно сохраняется в новой памяти. слот в стеке вызываемых методов.Внутри вызванного метода новая клонированная переменная указывает непосредственно на тот же объект в куче.Таким образом, его использование может изменить свойства одного и того же объекта.Но вы не можете изменить, на какой объект кучи указывает исходная ссылочная переменная (в стеке вызывающих методов).Если в вызываемом методе я пишу

  myVar = new object();

Исходная переменная в вызывающем методе не изменится и не укажет на новый объект.

Если я передаю ссылочный тип поRef, то я передаю указатель на объявленную переменную в стеке вызывающих методов (который содержит указатель на объект в куче). Следовательно, это указатель на указатель на объект.Он указывает на ячейку памяти в стеке вызовов методов, который указывает на объект в куче.
Итак, теперь, если я изменю значение переменной в вызываемом методе, установив для нее новый объект(), как указано выше, поскольку это «ссылка» на переменную в вызывающем методе, я фактически изменяю объект, который на которую указывает переменная в вызывающем методе.Итак, после возврата вызванного метода переменная в вызывающем методе больше не будет указывать на тот же исходный объект в куче.

ByVal должен быть вашим " по умолчанию " ;. Используйте его, если у вас нет особых причин использовать ByRef

Передача объекта ByVal в .net не делает копию объекта и не потребляет больше ресурсов, чем ByRef. Указатель все еще передается в функцию. Среда выполнения просто гарантирует, что вы не сможете изменить указатель в своей функции и вернуть для него другое значение. Вы все еще можете вносить изменения в значения в объекте, и вы увидите эти изменения вне функции. Вот почему ByRef используется так редко. Это необходимо только тогда, когда вы хотите, чтобы функция изменила реальный объект, который возвращается; следовательно, выходной параметр.

Используйте " ByRef " только в том случае, если параметром является «output» параметр. В противном случае используйте «ByVal». Использование " ByRef " на параметры, которые явно не должны возвращать значения, опасно и может легко генерировать ошибки.

Я бы сказал, что ByRef никогда не следует использовать - это плохая практика. Я бы применил это даже к своему типичному случаю использования - разрешить функции возвращать несколько значений (через параметры ByRef). Было бы лучше, если бы функция возвращала структурированный ответ, включающий эти множественные возвращаемые значения. Это более ясно и более очевидно, если функция возвращает значения только через оператор return.

Пометка определенных аргументов как ByRef показывает пользователю вашей функции, что переменная , назначенная этому аргументу **, будет изменена. ****

Если вы используете ByRef для всех аргументов, невозможно будет определить, какие переменные были изменены функцией, а какие просто прочитаны ею. (кроме просмотра внутри источника функции!)

По данным Microsoft, выбор ByVal или ByRef может повлиять на производительность для достаточно больших значений (см. Передача аргументов по значению и по ссылке (Visual Basic)):

Производительность.Хотя механизм прохождения может повлиять на производительность вашего кода, разница обычно незначительна.Единственным исключением из этого является тип значения, пройденного ByVal.В этом случае Visual Basic копирует все содержание данных аргумента.Поэтому, для большого значения тип, такой как структура, это может быть более эффективно Чтобы пройти его по ясно.

[курсив добавлен].

Sub last_column_process()
Dim last_column As Integer

last_column = 234
MsgBox last_column

trying_byref x:=last_column
MsgBox last_column

trying_byval v:=last_column
MsgBox last_column

End Sub

Sub trying_byref(ByRef x)
x = 345
End Sub

Sub trying_byval(ByRef v)
v = 555
End Sub

Много путаницы, которую я постараюсь упростить.По сути, у вас есть 4 варианта:

  1. Передайте тип значения поVal
  2. Передать тип значения поRef
  3. Передать объект по Val
  4. Передать объект поRef

Некоторые люди говорят, что вам следует никогда использовать по ссылке.Хотя они технически верны, одно можно сказать наверняка.Вам следует НИКОГДА используйте слово никогда.Если вы проектируете систему с нуля, следует избегать использования byRef любой ценой.Его использование обнажает недостаток дизайна.Однако работа над существующей системой может не обеспечить такой гибкости для реализации хорошего проекта.Иногда надо идти на уступки, т.е.используя ссылку.Например, если вы можете выполнить исправление за 2 дня, используя byRef, то это может быть предпочтительнее, чем заново изобретать велосипед и тратить неделю на получение того же исправления, чтобы избежать использования byRef.

Краткое содержание:

  1. Использование byVal для типа значения:Передает значение функции.Это предпочтительный способ разработки функций.
  2. Использование byRef для типа значения:Полезно для возврата более одного значения из функции.Если вы создаете функцию, которая должна вернуть более одного значения в существующую систему, это может быть лучше, чем создание объекта (и настройки свойств, и утилизация) только для одной функции.
  3. Использование byVal для объекта:Передает указатель объекта в функцию.Функция может изменить объект.
  4. Использование byRef для объекта:Передает указатель на указатель объекта на функцию.Позволяет изменять объект, на который указывает вызывающий абонент.Это может привести к тому, что некоторые трудно найти ошибки, и я не могу придумать ни одной веской причины, чтобы использовать их.Не означает, что его нет, но если их мало и далеко друг от друга.
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top