Г. Шилдт - С# 3.0 Полное руководство. 2010 (1160798), страница 43
Текст из файла (страница 43)
Попытаемся выяснить причины подобного влияния. Напомним, что при создании переменной типа класса формируется только ссылка иа объект. Поэтому при передаче этой ссылки методу принимающий ее параметр будет ссылаться иа тот же самый объект, иа который ссылается аргумент. Это означает, что и аргумент, и параметр ссылаются иа один и тот же объект и что объекты, по существу, передаются методам по ссылке. Тавмм образом, обьект в методе будетл оказывать влияние иа объект, используемый в качестве аргумента. Для примера рассмотрим следующую программу: // Перелача объектов по ссылке.
оядпд Буясели с1аяя Теяс ( рпвахс 1по а, Ьт роЬ1хс Тело(гпс 1, 1по 2) ( 214 Часть!. язык Сз а = ).; ь=0; ) /* Передать объект. Теперь переменные оЬ.а и оЬ.Ь из объекта, используемого в вызове метода, будут изменены. */ роЬ11с ко1б Сьапде(тезг оЫ ( оЬ.а = оЬ.а + оЬ.Ь; оЬ.Ь = -оЬ.Ьт ) с1азз Са11вувег ( зсаг1с ттокб Маьп() ( тезп оЬ = пен Тезв(15, 20) сопзо1е.хкьсеь1пе("оь.а и оь.ь до вызова: " + оь.а + " " + оь.ы ) оЬ.СЬапце(оЫ т Сопзо1е.икькеъ1пе("оЬ.а и оЬ.Ь после вызова: " + оЬ.а + " " + оЬ.Ы; ) ) Выполнение этой программы дает следующий результат: оЬ.а и оЬ.Ь до вызова: 15 20 оЬ.а и оЬ.Ь после вызова: 35 -20 Как видите, действия в методе Спапде () оказали в данном случае влияние на объект, использовавшийся в качестве аргумента.
Итак, подведем краткий итог. Когда объект передается методу по ссылке, сама ссылка передается по значению, а следовательно, создается копия этой ссылки. Но зта копия будет по-прежнему ссылаться на тот же самый объект, что и соответствующий аргумент.
Это означает, что объекты передаются методам неявным образом по ссылке. Использование модификаторов параметров ~ей и ои~ Как пояснялось выше, аргументы простых типов, например ьпг или спал, передаются методу по значению. Это означает, что изменения, вносимые в параметр, принимающий значение, не будут оказывать никакого влияния на аргумент, используемый для вызова.
Но такое поведение можно изменить, используя ключевые слова гег и опс для передачи значений обычных типов по ссылке. Это позволяет изменить в самом методе аргумент, указываемый при его вызове. Прежде чем переходить к особенностям использования ключевых слов ге 5 и опс, полезно уяснить причины, по которым значение простого типа иногда требуется передавать по ссылке. В общем, для этого существуют две причины: разрешить методу изменить содержимое его аргументов или же возвратить несколько значений. Рассмотрим каждую из этих причин более подробно. Глава 8. Подробнее о методах и классах 215 Нередко требуется, чтобы метод оперировал теми аргументами, которые ему передаются.
Характерным тому примером служит метод Яыар (), осуществляющий перестановку значений своих аргументов. Но поскольку аргументы простых типов передаются по значению, то, используя выбираемый в С() по умолчанию механизм вызова по значению для передачи аргумента параметру, невозможно написать метод, меняющий местами значения двух его аргументов, например типа 1пг. Это затруднение разрешает модификатор геб.
Как вам должно быть уже известно, значение возвращается из метода вызывающей части программы с помощью оператора геспгп. Но метод может одновременно возвратить лишь одно значение. А что, если из метода требуется возвратить два или более фрагментов информации, например, целую и дробную части числового значения с плавающей точкой7 Такой метод можно написать, используя модификатор опс. Использование модификатора параметра ~ей Модификатор параметра гег принудительно организует вызов по ссылке, а не по значению. Этот модификатор указывается как при объявлении, так и при вызове метода.
Для начала рассмотрим простой пример. В приведенной ниже программе создается метод Яцг (), возвращающий вместо своего аргумента квадрат его целочисленного значения. Обратите особое внимание на применение и местоположение модификатора гег. // Использовать модификатор гел для передачи значения // обычного типа по ссылке.
ия1пп Яуясего с1яяя Негтеяг ( // Этот метод изменяет свой аргумент. Обратите // внимание ня применение модификатора гег. рпнгас чо1б Яцг(гее 1пг 1) ( =1*1; ) ) с1аяя Кесвяио ( ягдс1с Нояб ид1п () ( негтеяг оь = пен вягтеяс()л 1пс а = 1сл Сопяо1е.иг1геъ1пе("я до вызова: " т а); оЬ.ЯЧг(гее я); // обратите внимание ня применение О модификатора тел Сопяо1е.игагеъапе("я после вызова: " т а); ) ) Как видите, модификатор геб указывается перед объявлением параметра в самом методе и перед аргументом при вызове метода. Ниже приведен результат выполнения данной программы, который подтверждает, что значение аргумента а действительно было изменено методом Яцг().
216 Часть ), язык Сз а до вызова: 10 а после вызова: 100 Теперь, используя модификатор хег, можно написать метод, переставляющий местами значения двух своих аргументов простого типа. В качестве примера ниже приведена программа, содержащая метод яиар (), производящий перестановку значений двух своих целочисленных аргументов, когда ои вызывается. // Поменять местами два значения. из1пд Яуатеап с1ааз иатиеЯиар ( // Этот метод меняет местами свои аргументы. риЬ11с чо10 яиар(гег зпт а, гег 1пе Ь) ( 1пс с( с=а; а =Ь; Ь=с; ) ) с1азз Уа1иеЯиарОезо ( зсагтс чо10 Ма1п() ( иа1иезиар оЬ = пен уа1иезиар() 1пв х = 10, у = 20; Сопао1е.вгьсе11пе("х и у до вызова: х + " " + у); оЬ.Янар(гет х, гег у); Сопзо1е.вг1иеЬ1пе("х и у после вызова: х+" "+у); Вот к какому результату приводит выполнение этой программы: х и у до вызова: 10 20 х и у после вызова: 20 10 В отношении модификатора ге1 необходимо иметь в виду следующее.
Аргументу, передаваемому по ссылке с помощью этого модификатора, должно быть присвоено зиачеиие до вызова метода. Дело в том, что в методе, получающем такой аргумент в качестве параметра, предполагается, что параметр ссылается на действительное значение. Следовательно, при использовании модификатора гег в методе нельзя задать первоначальное значение аргумента. Использование модификатора параметра очи Ииогда ссылочный параметр требуется использовать для получения значения из метода, а ие для передачи ему значения.
Допустим, что имеется метод, выполняющий некоторую функцию, например, открытие сетевого сокета и возврат кода успешиого или неудачного Глава 8, Подробнее о методах и классах 217 завершения данной операции в качестве ссылочиого параметра. В этом случае методу не передается никакой информации, ио в то же время ои должен возвратить определенную информацию. Главная трудность при этом состоит в том, что параметр гег должен быть ииициализировап определенным значением до вызова метода.
Следовательно, чтобы воспользоваться параметром гет, придется задать для аргумента фиктивное значение и тем самым преодолеть данное ограничение. Правда, в С(т имеется более подходящий вариант выхода из подобного затруднения — воспользоваться модификатором параметра оцс. Модификатор параметра оць подобен модификатору гег, за одним исключением: ои служит только для передачи значения за пределы метода. Поэтому переменной, используемой в качестве параметра оцс, ие нужно Гда и бесполезно) присваивать какое-то значение. Более того, в методе параметр оцо считается неинициализированным, т.е.
предполагается, что у него отсутствует первоначальное значение. Это означает, что значение должно быть присвоено данному параметру в методе до его завершения. Следовательно,, после вызова метода параметр оцс будет содержать некоторое значение. Ниже приведен пример применения модификатора параметра оць. В этом примере программы для разделения числа с плавающей точкой иа целую и дробную части используется метод песрагсз () из класса ()есоврозе. Обратите внимание иа то, как возвращается каждая часть исходного числа.
О Использовать модификатор параметра оцк. цз1пч зузсев; с1азз песоврозе ( /* Разделить числовое значение с плавающей точкой на целую и дробную части. */ рцЫ1с 1пс песрагсз(боцЬ1е и, оцс боцЫе тгас) ( 1пг иьо1ет ипо1е = (1по) и) тгас = и — ньо1ет // передать дробную часть числа // посредством параметра Ггас // возвратить целую часть числа гетнгп нво1е ) с1азз озеОцс ( зкастс уогз Ма1п() ( оесоврозе оЬ = пеи эесоврозе() 1пс 1) боцЫе Г) 1 = об.пеГРагсз(10.125, оцс Г) Сопзо1е.иг1сеЬхпе("Целая часть числа равна " + 1)т сопзо1е.иг1геыпе("дробная часть числа равна " + т); ) Выполнение этой программы дает следующий результат; Целая часть числа равна 10 Дробная часть числа равна 0.125 218 Часть ).
Язык С№ Метод аесрагьз () возвращает два фрагмента информации. Во-первых, целую часть исходного числового значения переменной и обычным образом с помощью оператора геспгп. И во-вторых, дробную часть этого значения посредством параметра ггас типа оис. Как показывает данный пример, используя модификатор параметра опт, можно организовать возврат двух значений из одного и того же метода.