Что такое out в c
Перейти к содержимому

Что такое out в c

  • автор:

Чем out отличается от ref?

Разница в том, что out — это выходной параметр, а ref — входно-выходной.

Для ref -параметра вы должны передать его инициализированным, и можете пользоваться его исходным значением. А для out -параметра вы не обязаны инициализировать его перед вызовом функции, не можете использовать его значение в функции до присваивания, и обязаны инициализировать его в функции.

(Таким образом, ref -параметр немного напоминает инициализированную локальную переменную, а out -параметр — неинициализированную.)

private void func1(out string value) < Console.WriteLine(value); // нельзя, value не инициализировано if (false) return; // нельзя, забыли установить значение value value = "Hello World!"; >string s1; func1(out s1); 
private void func2(ref string value) < Console.WriteLine(value); // можно if (false) return; // не проблема, у value остаётся старое значение value = "Hello World!"; >string s2; func2(ref s2); // нельзя, функция имеет право использовать значение, // значит, оно должно быть инициализировано сначала 

Таким образом, out -параметр — это как бы дополнительное возвращаемое значение функции. А ref -параметр — просто параметр, изменения которого видны снаружи функции.

На уровне CLR для out — и ref -параметров используется один и тот же механизм, но это незначительная техническая подробность. Разница в семантике.

ref в сравнении с out в C#

Ключевые слова Ref и out в C# используются для передачи аргументов внутри метода или функции. Оба слова указывают на то, что аргумент/параметр передается по ссылке. По умолчанию параметры передаются в метод по значению. Используя эти ключевые слова ( ref и out ), мы можем передать параметр по ссылке.

Ключевое слово ref

Ключевое слово ref передает аргументы по ссылке. Это означает, что любые изменения, внесенные в этот аргумент в методе, будут отражены в этой переменной, когда управление вернется к вызывающему методу.

Пример кода

public static string GetNextName(ref int id) < string returnText = "Next-" + id.ToString(); id += 1; return returnText; >static void Main(string[] args)

Вывод

Ключевое слово out

Ключевое слово out передает аргументы по ссылке. Это очень похоже на ключевое слово ref .

Пример кода

public static string GetNextNameByOut(out int id) < string returnText = "Next-" + id.ToString(); return returnText; >static void Main(string[] args)

Вывод

Ref в сравнении с Out

Параметр или аргумент должен быть сначала инициализирован, прежде чем он будет передан в ref .

Инициализация параметра или аргумента перед передачей его в out не является обязательной.

Не требуется присваивать или инициализировать значение параметра (который передается по ref ) перед возвратом в вызывающий метод.

Вызываемый метод обязан присвоить или инициализировать значение параметра (который передается в out ) перед возвратом в вызывающий метод.

Передача значения параметра по Ref полезна, когда вызываемый метод также должен модифицировать передаваемый параметр.

Объявление параметра в методе out полезно, когда из функции или метода необходимо вернуть несколько значений.

Инициализация значения параметра перед его использованием в вызывающем методе не обязательна.

Значение параметра должно быть инициализировано в вызывающем методе перед его использованием.

Когда мы используем REF , данные могут передаваться двунаправленно.

Когда мы используем OUT , данные передаются только однонаправленно (от вызываемого метода к вызывающему методу).

И ref , и out по-разному обрабатываются во время выполнения программы, а во время компиляции они обрабатываются одинаково.

Свойства не являются переменными, поэтому они не могут быть переданы в качестве параметра out или ref .

Ключевое слово Ref / Out и перегрузка методов

И ref , и out обрабатываются по-разному во время выполнения программы, и одинаково во время компиляции, поэтому методы не могут быть перегружены, если один метод принимает аргумент как ref , а другой — как out .

Пример кода

public static string GetNextName(ref int id) < string returnText = "Next-" + id.ToString(); id += 1; return returnText; >public static string GetNextName(out int id)

Вывод при компиляции кода:

Однако перегрузка методов возможна, когда один метод принимает аргумент ref или out , а другой принимает тот же аргумент без ref или out .

Пример кода

public static string GetNextName(int id) < string returnText = "Next-" + id.ToString(); id += 1; return returnText; >public static string GetNextName(ref int id)

Резюме

Ключевые слова out и ref полезны, когда мы хотим вернуть значение в тех же переменных, которые были переданы в качестве аргумента.

Материал подготовлен в рамках специализации «C# Developer». Если вам интересно узнать подробнее о формате обучения и программе, познакомиться с преподавателем курса — приглашаем на день открытых дверей онлайн. Регистрация здесь.

  • Блог компании OTUS
  • Программирование
  • C#

Что такое out в C#?

В языке C# ключевое слово out используется для передачи аргумента в метод так, чтобы метод мог модифицировать значение этого аргумента и вернуть его в вызывающий код. Это особенно полезно, когда метод должен вернуть несколько значения.

// Пример использования out в сигнатуре метода void ExampleMethod(out int result) < // result должен быть инициализирован внутри метода result = 42; >// Вызов метода с использованием out int outputValue; ExampleMethod(out outputValue); // outputValue теперь содержит значение 42

Комментарии

Пока комментариев нет

Профессия Front-end разработчик
Старт: 06 марта 2024

Изучение Python до профи / Основы, Django, TKinter

Создание сайта с нуля на CMS WordPress

Разработка игр на Python с нуля / Уроки Pygame

Что такое out в c

Существует два способа передачи параметров в метод в языке C#: по значению и по ссылке .

Передача параметров по значению

Наиболее простой способ передачи параметров представляет передача по значению, по сути это обычный способ передачи параметров:

void Increment(int n) < n++; Console.WriteLine($"Число в методе Increment: "); > int number = 5; Console.WriteLine($"Число до метода Increment: "); Increment(number); Console.WriteLine($"Число после метода Increment: ");
Число до метода Increment: 5 Число в методе Increment: 6 Число после метода Increment: 5

При передаче аргументов параметрам по значению параметр метода получает не саму переменную, а ее копию и далее работает с этой копией независимо от самой переменной.

Так, выше при вызове метод Increment получает копию переменной number и увеличивает значение этой копии. Поэтому в самом методе Increment мы видим, что значение параметра n увеличилось на 1, но после выполнения метода переменная number имеет прежнее значение — 5. То есть изменяется копия, а сама переменная не изменяется.

Передача параметров по ссылке и модификатор ref

При передаче параметров по ссылке перед параметрами используется модификатор ref :

void Increment(ref int n) < n++; Console.WriteLine($"Число в методе Increment: "); > int number = 5; Console.WriteLine($"Число до метода Increment: "); Increment(ref number); Console.WriteLine($"Число после метода Increment: ");
Число до метода Increment: 5 Число в методе Increment: 6 Число после метода Increment: 6

При передаче значений параметрам по ссылке метод получает адрес переменной в памяти. И, таким образом, если в методе изменяется значение параметра, передаваемого по ссылке, то также изменяется и значение переменной, которая передается на его место..

Так, в метод Increment передается ссылка на саму переменную number в памяти. И если значение параметра n в Increment изменяется, то это приводит и к изменению переменной number, так как и параметр n и переменная number указывают на один и тот же адрес в памяти.

Обратите внимание, что модификатор ref указывается как перед параметром при объявлении метода, так и при вызове метода перед аргументом, который передается параметру.

Выходные параметры. Модификатор out

Выше мы использовали входные параметры. Но параметры могут быть также выходными. Чтобы сделать параметр выходным, перед ним ставится модификатор out :

void Sum(int x, int y, out int result)

Здесь результат возвращается не через оператор return , а через выходной параметр result. Использование в программе:

void Sum(int x, int y, out int result) < result = x + y; >int number; Sum(10, 15, out number); Console.WriteLine(number); // 25

Причем, как и в случае с ref ключевое слово out используется как при определении метода, так и при его вызове.

Также обратите внимание, что методы, использующие такие параметры, обязательно должны присваивать им определенное значение. То есть следующий код будет недопустим, так как в нем для out-параметра не указано никакого значения:

void Sum(int x, int y, out int result)

Прелесть использования подобных параметров состоит в том, что по сути мы можем вернуть из метода не одно значение, а несколько. Например:

void GetRectangleData(int width, int height, out int rectArea, out int rectPerimetr) < rectArea = width * height; // площадь прямоугольника - произведение ширины на высоту rectPerimetr = (width + height) * 2; // периметр прямоугольника - сумма длин всех сторон >int area; int perimetr; GetRectangleData(10, 20, out area, out perimetr); Console.WriteLine($"Площадь прямоугольника: "); // 200 Console.WriteLine($"Периметр прямоугольника: "); // 60

Здесь у нас есть метод GetRectangleData, который получает ширину и высоту прямоугольника (параметры width и height). А два выходных параметра мы используем для подсчета площади и периметра прямоугольника.

При этом можно определять переменные, которые передаются out -параметрам в непосредственно при вызове метода. То есть мы можем сократить предыдущий пример следующим образом:

void GetRectangleData(int width, int height, out int rectArea, out int rectPerimetr) < rectArea = width * height; rectPerimetr = (width + height) * 2; >GetRectangleData(10, 20, out int area, out int perimetr); Console.WriteLine($"Площадь прямоугольника: "); // 200 Console.WriteLine($"Периметр прямоугольника: "); // 60

При этом, если нам неизвестен тип значений, которые будут присвоены параметрам, то мы можем для их определения использовать оператор var :

GetRectangleData(10, 20, out var area, out var perimetr); Console.WriteLine($"Площадь прямоугольника: "); // 200 Console.WriteLine($"Периметр прямоугольника: "); // 60

Входные параметры. Модификатор in

Кроме выходных параметров с модификатором out метод может использовать входные параметры с модификатором in . Модификатор in указывает, что данный параметр будет передаваться в метод по ссылке, однако внутри метода его значение параметра нельзя будет изменить. Например, возьмем следующий метод:

void GetRectangleData(in int width, in int height, out int rectArea, out int rectPerimetr) < //width = 25; // нельзя изменить, так как width - входной параметр rectArea = width * height; rectPerimetr = (width + height) * 2; >int w = 10; int h = 20; GetRectangleData(w, h, out var area, out var perimetr); Console.WriteLine($"Площадь прямоугольника: "); // 200 Console.WriteLine($"Периметр прямоугольника: "); // 60

В данном случае через входные параметры width и height в метод передаются значения, но в самом методе мы не можем изменить значения этих параметров, так как они определены с модификатором in .

Передача по ссылке в некоторых случаях может увеличить произодительность, а использование оператора in гарантирует, что значения переменных, которые передаются параметрам, нельзя будет изменить в этом методе.

ref-параметры только для чтения

В примерах выше можно было изменять значение ref -параметра. Однако иногда это может быть нежелательно. И чтобы гарантировать, что ref -параметр не изменит своего значения, начиная с версии C# 12 можно применять ref -параметры только для чтения. Такие параметры предваряются ключевым словом readonly :

void Increment(ref readonly int n) < // n++; // нельзя, иначе будет очишка компиляции Console.WriteLine($"Число в методе Increment: "); > int number = 5; Increment(ref number); Console.WriteLine($"Число после метода Increment: ");

В данном случае в метод Increment параметр n передается по ссылке и при этом он доступен только для чтения. При попытке изменить его значение мы получим ошибку на этапе компиляции.

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *