Методы способы передачи параметров
C#. Передача параметров в методы
Параметры методов
В этой статье, доступно рассказывается об особенностях передачи параметров в методы. Рассматривается передача параметров по значению, по ссылке, так же, чисто выходные параметры. Затрагиваются нюансы работы с типами значений и ссылочными типами.
Большая часть программистов сталкивается с необходимостью изучения данной темы, когда приходится изменять параметры, передаваемые в методы (не использовать их значения для вычисления чего-либо, а именно изменять значения, так, чтобы эти изменения сохранились после выполнения метода). И существует ряд нюансов, которые совсем не очевидны для начинающего программиста.
По умолчанию, в языке программирования C#, аргументы в методы передаются по значению! Но, Вы должны помнить, что большинство типов, используемых программистами, являются всё-таки ссылочными типами, и в результате, в метод попадает, так сказать, копия ссылки, так что, Вы можете изменять объект, на который ссылается эта копия (т.е. тот же объект, на который ссылает и оригинал ссылки), но не можете заставить оригинальную ссылку указывать на другой объект. А вот при использовании типов значений, ситуация иная, и проблемы могут всплыть сразу же!
Давайте представим, что нам нужно написать метод, который принимает два целых числа и меняет местами их значения, выглядеть такой метод может примерно так:
Казалось бы, ничего проще нет, но на практике, такой метод работать не будет! Если мы напишем код подобный следующему:
То мы увидим примерно такой результат работы приложения:
Результат работы метода Swap
Такой результат работы является следствием того, что аргументы передаются по значению, т.е. в метод передается копия аргумента, и сколько бы мы её не изменяли, за пределами метода, оригинал останется неизменным. Но ситуацию, можно исправить очень просто! Нужно указать при объявлении метода, что параметры должны передаваться по ссылке. Для этого в C# существует ключевое слово ref, которое указывается перед аргументом при объявлении и при вызове метода. На практике, доработанный метод «Swap» это выглядит так:
А вызов метода «Swap» будет таким:
И тогда, результат работы метода, будет таким:
Результат работы доработанного метода Swap
Как видите, подобные проблемы решаются передачи параметров в методы решаются довольно просто, даже не пришлось переписывать «логику» метода. Но есть одна особенность, объект, который передается в качестве ref-параметра метода, должен быть инициализирован перед вызовом метода. Т.е. подобный код, компилироваться не будет:
Но бывают такие ситуации, когда перед передаче объекта в метод, который должен изменить его значение, мы не знаем чем инициализировать данный объект (можно конечно инициализировать его чем попало, но это это довольно коряво), в таких случаях можно передать параметр в метод не как ссылочный, как чисто выходной параметр. Делается это просто, ключевое слово ref, заменяется на ключевое слово out.
Представим, что нам нужно написать метод, который должен принимать не инициализированный целочисленный параметр, заполнять его случайным значением. Выглядеть это может примерно так:
Использовать метод можно так:
Пример, конечно надуманный, можно было бы не работать с выходными параметрами, а просто возвращать случайное значение методом «SetValue», но в реальной практике, можно столкнуться с ситуацией, что метод уже возвращает какое-то значение, или нужно заполнить несколько выходных параметров.
А теперь вернемся к ссылочным типам! С ними всё немножко иначе, в метод попадает копия ссылки, это значит, что изменять состояние объекта, на который указывает ссылка мы можем, в отличии от типов значений. Но вот поменять местами два объекта, даже ссылочного типа, в «лоб» не получится, всё равно придется прибегать к использованию ссылочных параметров, но это и проблема! Правда?
Добавить комментарий Отменить ответ
Для отправки комментария вам необходимо авторизоваться.
Источник
Java: передача параметров по значению или по ссылке
Простое объяснение принципов передачи параметров в Java.
Многие программисты часто путают, какие параметры в Java передаются по значению, а какие по ссылке. Давайте визуализируем этот процесс, и тогда вы увидите насколько все просто.
Данные передаются между методами через параметры. Есть два способа передачи параметров:
Передача по значению (by value). Значения фактических параметров копируются. Вызываемый метод создает свою копию значений аргументов и затем ее использует. Поскольку работа ведется с копией, на исходный параметр это никак не влияет.
Передача по ссылке (by reference). Параметры передаются как ссылка (адрес) на исходную переменную. Вызываемый метод не создает свою копию, а ссылается на исходное значение. Следовательно, изменения, сделанные в вызываемом методе, также будут отражены в исходном значении.
В Java переменные хранятся следующим образом:
Локальные переменные, такие как примитивы и ссылки на объекты, создаются в стеке.
Объекты — в куче (heap).
Теперь вернемся к основному вопросу: переменные передаются по значению или по ссылке?
Java всегда передает параметры по значению
Чтобы разобраться с этим, давайте посмотрим на пример.
Пример передачи примитивов по значению
Поскольку Java передает параметры по значению, метод processData работает с копией данных. Следовательно, в исходных данных (в методе main ) не произошло никаких изменений.
Теперь рассмотрим другой пример:
Передача объекта
Что здесь происходит? Если Java передает параметры по значению, то почему был изменен исходный список? Похоже, что Java все-таки передает параметры не по значению? Нет, неправильно. Повторяйте за мной: «Java всегда передает параметры по значению».
Чтобы с этим разобраться, давайте посмотрим на следующую диаграмму.
Память стека (stack) и кучи (heap)
В программе, приведенной выше, список fruits передается методу processData . Переменная fruitRef — это копия параметра fruit . И fruits и fruitsRef размещаются в стеке. Это две разные ссылки. Но самое интересное заключается в том, что они указывают на один и тот же объект в куче. То есть, любое изменение, которое вы вносите с помощью любой из этих ссылок, влияет на объект.
Давайте посмотрим на еще один пример:
Передача объекта по ссылке
Память стека (stack) и кучи (heap)
В этом случае для изменения ссылки fruitRef мы использовали оператор new . Теперь fruitRef указывает на новый объект, и, следовательно, любые изменения, которые вы вносите в него, не повлияют на исходный объект списка фруктов.
Итак, Java всегда передает параметры по значению. Однако мы должны быть осторожны при передаче ссылок на объекты.
Вышеприведенная концепция очень важна для правильного решения ваших задач.
Например, рассмотрим удаление узла в односвязном списке.
Удаление узла в связанном списке
Это решение работает во всех случаях, кроме одного — когда вы удаляете первый узел ( Position = 1 ). Основываясь на ранее описанной концепции, видите ли вы в чем здесь проблема? Возможно, поможет следующая диаграмма.
Удаление первого узла односвязного списка
Для исправления алгоритма необходимо сделать следующее:
В этой статье мы обсудили одну небольшую, но важную концепцию Java: передачу параметров.
Подробнее о курсе и программе обучения можно узнать на бесплатном вебинаре, который пройдет 15 апреля.
Источник
Способы передачи параметров функциям
Механизм параметров является основным способом обмена информацией между вызываемой и вызывающей функциями. В операторе вызова функции записывают аргументы функции, а в заголовке описания функции перечисляют параметры.
В С++ передача параметров осуществляется тремя способами:
· по копии (или по значению);
· по адресу (или через указатель);
Это определяется видом объявления параметра в заголовке функции.
Рассмотрим все три способа передачи на примере функции обмена Change(). Ей передаются два параметра, и она должна поменять местами их значения.
1. Передача по копии (по значению):
При передаче по значению объявление параметра похоже на объявление переменной: Тип ИмяПараметра. Такой параметр считается отдельной локальной переменной в теле функции. Ни в заголовке, ни в теле функции не должно быть других параметров или переменных с таким же именем.
Опишем работу программы. В области видимости функции main() существуют две локальные переменные A и B, которые проинициализированы значениями 10 и 20. В момент вызова функции Change() в стеке создаются параметры X и Y, которые получают копии значений аргументов A и B, а также переменная temp. Затем с помощью этой переменной происходит перестановка значений параметров X и Y (прежние значения выделены красным цветом). Однако по окончании работы функции Change() переменные X, Y и temp уничтожаются, поскольку являются локальными переменными, а значения аргументов A и B остаются неизменными.
Таким образом, функция Change() не решает поставленной перед ней задачи. Тем не менее, данный пример иллюстрирует особенность использования параметров-копий: никакие изменения значения параметра внутри функции не отражаются на значении переменной-аргумента, так как параметр является локальной переменной. Это способ передачи параметров в C++ используется по умолчанию.
2. Передача по адресу (через указатель):
Способ передачи параметров по адресу используется для того, чтобы через указатели обеспечить непосредственный доступ к значениям аргументов. В момент вызова функции Change() в стеке создаются параметры-указатели X и Y, которые получают копии адресов аргументов A и B. Теперь параметры X и Y указывают на аргументы A и B. Несмотря на то, что функции Change() не известны имена аргументов A и B, ей известны их адреса, поэтому она имеет доступ к их значениям. С помощью переменной temp происходит перестановка значений аргументов A и B (прежние значения выделены красным цветом). По окончании работы функции Change() переменные X, Y и temp уничтожаются, поскольку являются локальными переменными, но аргументы A и B остаются с новыми значениями. Таким образом, функция выполнила поставленную задачу.
3. Передача по ссылке:
Этот способ передачи параметров появился в C++ для того, чтобы упростить работу с указателями. При передаче по ссылке объявление параметра представляет собой объявление ссылки без инициализации: Тип &ИмяПараметра. Параметр-ссылка локальна в функции: ни в заголовке, ни в ее теле не должно быть объявлено других параметров и переменных с таким же именем. Инициализация параметра-ссылки выполняется во время вызова функции.
В самом простом случае при вызове функции в качестве аргумента задается имя переменной. Тип переменной-аргумента должен совпадать с типом параметра-ссылки. Ссылка становится альтернативным именем аргумента, поэтому любые действия, выполняемые со ссылкой в теле функции, мгновенно отражаются на состоянии аргумента.
В момент вызова функции Change() у аргументов A и B появляются вторые имена X и Y. Поэтому функция Change фактически напрямую работает с исходными переменными A и B и изменяет их.
Использование параметров-ссылок вместо передачи по значению или по адресу более эффективно, поскольку:
1) не требуется памяти для копирования аргументов в локальные переменные;
2) не требуется времени на их создание и уничтожение.
Поэтому программы с параметрами-ссылками работают быстрее и используют меньше памяти. Это имеет значение при передаче структур данных большого объема.
Передача параметра по ссылке также используется, если функция должна возвратить не один результат, а несколько.
Если требуется запретить изменение параметра, передаваемого по адресу или по ссылке, то используется модификатор const, например:
int Func( int a, const double &b);
СОВЕТ Рекомендуется указывать const перед всеми параметрами, изменение которых в функции не предусмотрено. Это облегчает отладку. Кроме того, на место параметра типа const& может передаваться константа.
Параметры, передаваемые в функцию, могут быть любого типа (например, вещественного, структурой, перечислением, объединением, указателем), кроме массива или функции, которые передаются с помощью указателей.
Источник