Подтвердить что ты не робот

Лучшая практика: ByRef или ByVal? в .Net

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

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

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

4b9b3361

Ответ 1

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

Вы почти всегда хотите пройти по значению. Передача по ссылке почти всегда выполняется для "Я хочу вернуть несколько результатов, а не просто добавляя вещи в список, который передается". Классическим примером метода, использующим pass-by-reference, является Int32.TryParse, где возвращаемое значение является успешным/неудачным, а проанализированное значение равно "возвращен" параметром out.

Ответ 2

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

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

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

  myVar = new object();

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

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

Ответ 3

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

Ответ 4

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

Ответ 5

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

Ответ 6

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

Ответ 7

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

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

Ответ 8

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

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

[выделено курсивом].

Ответ 9

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

Ответ 10

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

  • передать тип значения byVal
  • Передайте тип значения byRef
  • Передача объекта byVal
  • Передача объекта byRef

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

Резюме:

  • Использование byVal по типу значения: передает значение функции. Это предпочтительный способ конструкторских функций.
  • Использование byRef для типа значения: полезно для возврата более одного значения из функции. если ты создают функцию, которая должна возвращать более одного значения для существующая система может быть лучше, чем создание объекта (и настройка свойств и удаление) только для одной функции.
  • Использование byVal для объекта: передает указатель объекта на функцию. Функция может изменить объект.
  • Использование byRef для объекта: передает указатель на указатель объекта на функцию. Позволяет изменение объекта, на который указывает вызывающий. Это может привести к трудно найти ошибки, и я не могу придумать никаких оснований для его использования. Не означает, что нет одного, но если их нет, и далеко между ними.

Ответ 11

Джо ваше объяснение довольно ясное и очень полезно. Спасибо:)