C# 4.0 полное руководство - 2011
Шрифт:
Модификатор параметра 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("х и у после вызова: " + х + " " + у);
}
}
Вот к какому результату приводит выполнение этой программы.
х и у до вызова: 10 20 х и у после вызова: 20 10
В отношении модификатора ref необходимо иметь в виду следующее. Аргументу, передаваемому по ссылке с помощью этого модификатора, должно быть присвоено значение до вызова метода. Дело в том, что в методе, получающем такой аргумент в качестве параметра, предполагается, что параметр
Использование модификатора параметра out
Иногда ссылочный параметр требуется использовать для получения значения из метода, а не для передачи ему значения. Допустим, что имеется метод, выполняющий некоторую функцию, например, открытие сетевого сокета и возврат кода успешного или неудачного завершения данной операции в качестве ссылочного параметра. В этом случае методу не передается никакой информации, но в то же время он должен возвратить определенную информацию. Главная трудность при этом состоит в том, что параметр типа ref должен быть инициализирован определенным значением до вызова метода. Следовательно, чтобы воспользоваться параметром типа ref, придется задать для аргумента фиктивное значение и тем самым преодолеть данное ограничение. Правда, в C# имеется более подходящий вариант выхода из подобного затруднения — воспользоваться модификатором параметра out.
Модификатор параметра out подобен модификатору ref, за одним исключением: он служит только для передачи значения за пределы метода. Поэтому переменной, используемой в качестве параметра out, не нужно (да и бесполезно) присваивать какое-то значение. Более того, в методе параметр out считается неинициализированным, т.е. предполагается, что у него отсутствует первоначальное значение. Это означает, что значение должно быть присвоено данному параметру в методе до его завершения. Следовательно, после вызова метода параметр out будет содержать некоторое значение.
Ниже приведен пример применения модификатора параметра out. В этом примере программы для разделения числа с плавающей точкой на целую и дробную части используется метод GetParts из класса Decompose. Обратите внимание на то, как возвращается каждая часть исходного числа.
// Использовать модификатор параметра out.
using System;
class Decompose {
/* Разделить числовое значение с плавающей точкой на целую и дробную части. */ public int GetParts(double n, out double frac) { int whole;
whole = (int) n;
frac = n - whole; // передать дробную часть числа через параметр frac return whole; // возвратить целую часть числа
}
}
class UseOut {
static void Main {