- •Вопрос 1 – ilasm,ildasm,Reflecrion, устройство сборок
- •Вопрос 2. Архитектура платформы .Net. Основные компоненты платформы.
- •Вопрос 3. Выполнение приложений на платформе Microsoft .Net.
- •Вопрос 4. Компиляция и выполнение приложений на платформе Microsoft .Net.
- •Вопрос 5. Атрибуты
- •Вопрос 6. Net.Framework
- •Вопрос 7. Библиотеки System.Io.
- •Вопрос 8. Взаимодействие с неуправляемым кодом
- •Вопрос 9. Циклы
- •Вопрос 10-11. Делегаты
- •Вопрос 12. Классы объекты….
- •Вопрос 13. Компонентное программирование.
- •14. Концепция примененя программных платформ.
- •Вопрос 15. Объявление массивов.
- •Вопрос16. Исключения
- •Вопрос 18. Ветвление программ
- •Вопрос 20. Типы данных приведение типов данных.
- •Вопрос 21 - Отличие Windows forms от wi32 api
- •Вопрос 23. Пространство имён
- •Вопрос 24. Поток.
- •Вопрос 25. Работа с файлами.
- •Вопрос 26. Работа с файлами и дерикториями .Net
- •Вопрос 27. Роль clr.
- •Вопрос 28. Синхронизация потоков.
- •Вопрос 29. Передача параметров по ссылке.
- •Вопрос 30. Строгая и нестрогая типизация.
- •Вопрос 31. Структура программы и методы.
- •Вопрос 32. Коллекции в .Net
- •Вопрос 33. Модель программирования Windows Forms
Вопрос 29. Передача параметров по ссылке.
Параметры ref и out
При попытке получения информации с помощью метода на С# вы получите только возвращаемое значение. Поэтому может показаться, что в результате вызова метода вы получите не более одного значения. Очевидно, что отдельно вызывать метод для каждой порции данных во многих ситуациях будет очень неуклюжим решением. Допустим, у вас есть класс Color, представляющий любой цвет в виде трех значений согласно стандарту RGB (красный-зеленый-синий). Использование лишь возвращаемых значений вынудит вас написать следующий код, чтобы получить все три значения:
// Предполагаем, что color - экземпляр класса Color, int red = color. GetRedQ; int green = color.GetGreenO; int blue = color. GetBlueQ;
Но нам хочется получить что-то вроде этого:
int red;
int green;
int blue;
color.GetRGB(red,green,blue);
Но при этом возникает проблема. При вызове метода color.GetRGB значения аргументов red, green и blue копируются в локальный стек метода, а переменные вызывающей функции остаются без изменений, сделанных методом.
На C++ эта проблема решается путем передачи при вызове метода указателей или ссылок на эти переменные, что позволяет методу обрабатывать данные вызывающей функции. Решение на С# выглядит аналогично. На самом деле С# предлагает два похожих решения. Первое из них использует ключевое слово ref. Оно сообщает компилятору С#, что передаваемые аргументы указывают на ту же область памяти, что и переменные вызывающего кода. Таким образом, если вызванный метод изменяет их и возвращает управление, переменные вызывающего кода также подвергнутся изменениям. Следующий код иллюстрирует использование ключевого слова ref на примере класса Color.
using System;
class Color {
public Color() {
this.red = 255; this.green = 0; this.blue = 125; }
protected int red; protected int green; protected int blue;
public void GetColors(ref int red, ref int green, ref int blue) {
red = this.red; green = this.green; blue = this.blue; > }
class RefTestlApp {
public static void MainQ
{
Color color = new ColorQ;
int red;
int green;
int blue;
color.GetColors(ref red, ref green, ref blue);
Console.WriteLine("red = {0}, green = {1}.
blue = {2}", red, green, blue);
} }
У ключевого слова ref есть один недостаток, а приведенный код фактически не будет компилироваться. При использовании ключевого слова re/перед вызовом метода вы должны инициализировать передаваемые аргументы. Поэтому, чтобы этот код заработал, его нужно изменить:
using System;
class Color {
public ColorQ {
this.red = 255; this.green = 0; this.blue = 125; }
protected int red; protected int green; protected int blue;
public void GetColors(ref int red, ref int green, ref int blue)
{red = this.red;
green = this.green; blue = this.blue; } }
class RefTest2App {
public static void MainQ {
Color color = new ColorO; int red = 0; int green = 0;
int blue = 0;
color.GetColors(ref red, ref green, ref blue); Console.
WriteLineC 1 red = {0}, green = {1}, blue = {2}", red, green, blue);
} }
He кажется ли вам, что инициализация переменных, которые позже будут перезаписаны, бессмысленна? Поэтому С# предоставляет альтернативный способ передачи аргументов, изменения значений которых должны быть видимыми вызывающему коду: с помощью ключевого слова out. Вот пример с тем же классом Color, где используется out
using System;
class Color {
public Color() {
this.red = 255; this.green = 0; this.blue = 125; }
protected int red;
protected int green;
protected int blue;
public void GetColors(out int red, out int green, out int blue) <
red = this.red;
green = this, green; blue = this.blue; } >
class OutTestlApp {
public static void MainQ {
Color color = new ColorO; int red; int green; int blue;
color.6etColors(out red, out green, out blue); Console.WriteLine("red = {0}, green = {1}, blue = {2}",
red, green, blue); } }
Единственное различие между ключевыми словами ref и out в том, что out не требует, чтобы вызывающий код сначала инициализировал передаваемые аргументы. А когда же применять ref! Когда нужна гарантия, что вызывающий код инициализировал аргумент. В приведенных примерах можно было применять ключевое слово out, так как вызываемый метод не зависит от значения передаваемой переменной. Ну а если вызываемый метод использует значение параметра? Взгляните:
using System;
class Window {
public Window(int x, int y) {
this.x = x; this.у = у; }
protected int x; protected int y;
public void Move(int x, int y) {
this.x = x; this,у = у; }
public void ChangePos(ref int x, ref int y) {
this.x += x;;
this.у += у;
x = this.x; у = this.у; } }
class OutTest2App {
public static void Main()
{
Window wnd = new Window(5, 5);
int x = 5; int у = 5;
wnd.ChangePos(ref x, ref y);
Console.WriteLine("{0}, {1}", x, y);
x = -1; У = -1;
wnd.ChangePos(ref x, ref y);
Console.WriteLine("{0}, {1}", x, y); } >
Как видите, работа вызываемого метода Window.Change Pos основана на переданных ему значениях. В данном случае ключевое слово ref вынуждает вызывающий код инициализировать эти значения, чтобы метод работал корректно.