ob.a и ob.b до вызова: 15 20 ob.a и ob.b после вызова: 35 -20 Как видите, действия в методе Change оказали в данном случае влияние на объект, использовавшийся в качестве аргумента. Итак, подведем краткий итог. Когда объект передается методу по ссылке, сама ссыл ка передается по значению, а следовательно, создается копия этой ссылки. Но эта ко пия будет по-прежнему ссылаться на тот же самый объект, что и соответствующий ар гумент. Это означает, что объекты передаются методам неявным образом по ссылке. ## Использование модификаторов параметров ref и out Как пояснялось выше, аргументы простых типов, например int или char, переда ются методу по значению. Это означает, что изменения, вносимые в параметр, прини мающий значение, не будут оказывать никакого влияния на аргумент, используемый для вызова. Но такое поведение можно изменить, используя ключевые слова ref и out для передачи значений обычных типов по ссылке. Это позволяет изменить в самом методе аргумент, указываемый при его вызове. Прежде чем переходить к особенностям использования ключевых слов ref и out, полезно уяснить причины, по которым значение простого типа иногда требуется пе редавать по ссылке. В общем, для этого существуют две причины: разрешить методу изменить содержимое его аргументов или же возвратить несколько значений. Рассмо трим каждую из этих причин более подробно. Нередко требуется, чтобы метод оперировал теми аргументами, которые ему пере даются. Характерным тому примером служит метод Swap, осуществляющий пере становку значений своих аргументов. Но поскольку аргументы простых типов пере даются по значению, то, используя выбираемый в C# по умолчанию механизм вызова по значению для передачи аргумента параметру, невозможно написать метод, меняю щий местами значения двух его аргументов, например типа int. Это затруднение раз решает модификатор ref. Как вам должно быть уже известно, значение возвращается из метода вызывающей части программы с помощью оператора return. Но метод может одновременно воз вратить лишь одно значение. А что, если из метода требуется возвратить два или более фрагментов информации, например, целую и дробную части числового значения с плавающей точкой? Такой метод можно написать, используя модификатор out. ### Использование модификатора параметра ref Модификатор параметра ref принудительно организует вызов по ссылке, а не по значению. Этот модификатор указывается как при объявлении, так и при вызове мето да. Для начала рассмотрим простой пример. В приведенной ниже программе создает ся метод Sqr, возвращающий вместо своего аргумента квадрат его целочисленного значения. Обратите особое внимание на применение и местоположение модификато ра ref.
// Использовать модификатор ref для передачи значения обычного типа по ссылке. using System;
class RefTest { // Этот метод изменяет свой аргумент. Обратите // внимание на применение модификатора ref. public void Sqr(ref int i) { i = i * i; } }
class RefDemo { static void Main { RefTest ob = new RefTest; int a = 10; Console.WriteLine("а до вызова: " + a); ob.Sqr(ref a); // обратите внимание на применение модификатора ref Console.WriteLine("а после вызова: " + а); } } Как видите, модификатор ref указывается перед объявлением параметра в самом методе и перед аргументом при вызове метода. Ниже приведен результат выполнения данной программы, который подтверждает, что значение аргумента а действительно было изменено с помощью метода Sqr.
а до вызова: 10 а после вызова: 100 Теперь, используя модификатор ref, можно написать метод, переставляющий ме стами значения двух своих аргументов простого типа. В качестве примера ниже при ведена программа, в которой метод Swap выполняет перестановку значений двух своих целочисленных аргументов, когда он вызывается.
// Поменять местами два значения. using System;
class ValueSwap { // Этот метод меняет местами свои аргументы. public void Swap(ref int a, ref int b) { int t; t = a; a = b; b = t; } }
class ValueSwapDemo { static void Main { ValueSwap ob = new ValueSwap; int x = 10, у = 20; Console.WriteLine("x и у до вызова: " + х + " " + у); ob.Swap(ref х, ref у); Console.WriteLine("х и у после вызова: " + х + " " + у); } } Вот к какому результату приводит выполнение этой программы.