Форум программистов, компьютерный форум, киберфорум
C# для начинающих
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.84/277: Рейтинг темы: голосов - 277, средняя оценка - 4.84
5 / 5 / 0
Регистрация: 19.05.2012
Сообщений: 86
1

Каковы суть и назначение ref и out

30.07.2012, 12:42. Показов 50281. Ответов 13
Метки нет (Все метки)

Читал книги, юзал msdn, но все равно не смог понять про операторы ref и out, точнее про ref немножко понял.
__________________
Помощь в написании контрольных, курсовых и дипломных работ здесь
1
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
30.07.2012, 12:42
Ответы с готовыми решениями:

Делегаты и события - каковы их суть и назначение
Привет. Сейчас изучаю C#. Подошел к теме делегатов и событий. И вот если с делегатами еще...

Каковы суть и назначение Unit Tests
Всем привет! Народ, что такое Юнит тесты? с чем их едят и для чего вообще нужны? Расскажите кому...

События в .NET - каковы их концепция и назначение?
Я просто не могу понять концепцию событий и зачем они вообще нужны. С делегатом тут всё понятно,...

Поразрядные операторы - их суть и назначение
Господа, подскажите пожалуйста, что делают поразрядные операторы, если можно, то пожалуйста на...

13
Эксперт Java
4077 / 3811 / 745
Регистрация: 18.05.2010
Сообщений: 9,331
Записей в блоге: 11
30.07.2012, 12:47 2
В C# значения переменных по-умолчанию передаются по значению.
То есть:
C#
1
2
3
4
5
6
7
8
9
10
void changeVar(int v)
{
   v = 1;
}
public static void Main(string[] args)
{
   int myVar = 2;
   changeVar(myVar);
   Console.WriteLine(myVar);
}
Выведет 2, хотя мы пытались поменять значение в методе.

Теперь добавим ref, и получим уже 1.
C#
1
2
3
4
5
6
7
8
9
10
void changeVar(ref int v)
{
   v = 1;
}
public static void Main(string[] args)
{
   int myVar = 2;
   changeVar(ref myVar);
   Console.WriteLine(myVar);
}
Теперь метод changeVar меняет значение исходной переменной, а не копии, которая передалась, как в первом варианте.
16
Эксперт .NET
4355 / 2018 / 391
Регистрация: 27.03.2010
Сообщений: 5,492
Записей в блоге: 1
30.07.2012, 13:12 3
Ни знаю, достаточно ли понятно расписал. Но думаю чуть приоткрывает завесу, что же за ref и out.
C#
1
2
3
4
5
6
7
8
9
10
    public class Person
    {
        public string Name { get; set; }
        public uint Age { get; set; }
 
        public override string ToString()
        {
            return string.Format("Возраст: {0} Имя: {1}", Age, Name);
        }
    }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
    class Program
    {
        static void Main(string[] args)
        {
            Person person1 = new Person() { Age = 18, Name = "Изначально созданный" };
 
            Console.WriteLine("Вызываем метод: GetPersonWithoutRefOrOut");
            GetPersonWithoutRefOrOut(person1);
            Console.WriteLine("Результат его работы:");
            Console.WriteLine(person1);
            Console.WriteLine("Как видно созданный объект внутри метода не передался" +
                " за его пределы, так как на него ссылалась копия ссылки Person\n");
 
            Person person2;
 
            GetPersonRef(ref person1);
            GetPersonOut(out person2);
 
            Console.WriteLine(person1);
            Console.WriteLine(person2);
 
            Console.ReadKey();
        }
 
        //передаётся копия ссылки Person
        public static void GetPersonWithoutRefOrOut(Person person) 
        {   
            person = new Person() { Age = 90, Name = "Из метода without ref or out" };
        }
 
        //передаётся ссылка по ссылке, но передаваемая ссылка
        //должна быть инициализирована хотя бы null
        public static void GetPersonRef(ref Person person) 
        {
            person = new Person() { Age = 20, Name = "Из метода ref" };
        }
 
        //передаётся ссылка по ссылке, но передаваемая ссылка
        //может быть не инициализирована, но обязательно должна 
        //быть инициализирована внутри метода
        public static void GetPersonOut(out Person person) 
        {
            person = new Person() { Age = 30, Name = "Из метода out" };
        }
    }
2
Эксперт .NET
15562 / 11810 / 3099
Регистрация: 17.09.2011
Сообщений: 19,725
30.07.2012, 13:13 4
out - тот же ref, но с условием, что параметру в методе должно быть присвоено значение.
5
711 / 678 / 126
Регистрация: 30.03.2012
Сообщений: 1,124
30.07.2012, 13:24 5
Лучший ответ Сообщение было отмечено как решение

Решение

Цитата Сообщение от kolorotur Посмотреть сообщение
out - тот же ref, но с условием, что параметру в методе должно быть присвоено значение.
разве не стоит добавить что ref предполагает значение имеющееся ДО передачи его в метод, а out нет?
применяя ref мы можем использовать значение в методе, при этом его можно изменить, а можно и оставить какое было
применяя out нельзя использовать значение в методе, только присвоить (оставить каким было - нельзя, по той причине что в методе мы не знаем каким же оно было изначально и х=х не сработает)

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
        static void Main(string[] args)
        {
            int n;
            Out(out n); // нет ошибки - х не обязано быть определено
            int q;
            Ref(ref q); // ошибка - ref предполагает наличие значения
 
        }
        public static void Out(out int x)
        {
            x = x / 2; // ошибка - нельзя использовать х
        }
        public static void Ref(ref int x)
        {
            x = x / 2; // нет ошибки, х определено
        }
        public static void OutWO(out int x)
        {
            // ошибка - нельзя оставить х неизменным, х=х также не катит
        }
        public static void RefWO(ref int x)
        {
            // нет ошибки, не хочешь - не меняй х
        }
8
Эксперт .NET
15562 / 11810 / 3099
Регистрация: 17.09.2011
Сообщений: 19,725
30.07.2012, 13:45 6
Цитата Сообщение от Tessen Посмотреть сообщение
разве не стоит добавить что ref предполагает значение имеющееся ДО передачи его в метод, а out нет?
Это автоматически следует из правила обязательного присваивания переменной (любой) до ее использования.
0
5 / 5 / 0
Регистрация: 19.05.2012
Сообщений: 86
30.07.2012, 14:00  [ТС] 7
Casper-SC, стойте а что значит в твоем коде: {0} Имя: {1} они же не выводятся
0
Эксперт .NET
4355 / 2018 / 391
Регистрация: 27.03.2010
Сообщений: 5,492
Записей в блоге: 1
30.07.2012, 14:06 8
Цитата Сообщение от KiberKam Посмотреть сообщение
Casper-SC, стойте а что значит в твоем коде: {0} Имя: {1} они же не выводятся
Как не выводятся? Выводятся на строках:
C#
1
Console.WriteLine(person1);
и т.д.
0
5 / 5 / 0
Регистрация: 19.05.2012
Сообщений: 86
30.07.2012, 14:10  [ТС] 9
Casper-SC, нет, я имею ввиду что фигурные скобки со 0 и 1 не выводятся на консоль
0
9 / 9 / 2
Регистрация: 21.05.2012
Сообщений: 53
30.07.2012, 14:34 10
Уж странно вы читаете Шилдта, читайте внимательнее и все ) страница 76 и дальше все очень хорошо объясняет.
1
Эксперт .NET
4355 / 2018 / 391
Регистрация: 27.03.2010
Сообщений: 5,492
Записей в блоге: 1
30.07.2012, 16:07 11
Цитата Сообщение от KiberKam Посмотреть сообщение
Casper-SC, нет, я имею ввиду что фигурные скобки со 0 и 1 не выводятся на консоль
Есть такая фишка, как щёлкаешь по непонятному методу мышкой и жмёшь F1 и читаешь документацию.
0
52 / 45 / 4
Регистрация: 07.10.2010
Сообщений: 95
30.07.2012, 22:31 12
Цитата Сообщение от kolorotur Посмотреть сообщение
out - тот же ref, но с условием, что параметру в методе должно быть присвоено значение.
Тут еще можно добавить, что при написании методов компилятор считает ref и out одним типом.

И на конструкцию
C#
1
2
3
4
5
6
7
8
        public void SomeMetod(out int x)
        {
           return;
        }
        public void SomeMetod(ref int x)
        {
            return;
        }
ругнется и скажет что б использовали разные типы при перегрузки.

А вот такое откомпилится нормально.
C#
1
2
3
4
5
6
7
8
        public void SomeMetod(int x)
        {
           return;
        }
        public void SomeMetod(ref int x)
        {
            return;
        }
1
20 / 20 / 0
Регистрация: 05.02.2011
Сообщений: 65
31.07.2012, 00:59 13
Простым языком можно сказать так, что если Вы немного поняли значение оператора ref, то применяйте out только в том случае когда значение нужно возвратить ИЗ метода, и в коде до этого ранее не употреблялось.
1
1 / 1 / 1
Регистрация: 08.09.2016
Сообщений: 2
08.09.2016, 10:59 14
Модификатор out передает в метод неинициализированную переменную, которую мы там должны инициализировать, при передаче в метод мы лишь должны определить её тип:
C#
1
2
3
4
5
6
7
8
9
10
11
        static void Main(string[] args)
        {
            int a;
            Meth(out a);
 
        }
 
        static void Meth(out int a)
        {
            a = 2;
        }
При этом будет ли проинициализирована переменная или нет до передачи в метод, не имеет значения, т.к. в методе мы всё равно не сможем получить значение переменной с модификатором out:
C#
1
2
3
4
5
6
7
8
9
10
11
12
     static void Main(string[] args)
        {
            int a=2;
            Meth(out a);
        }
              
        static void Meth(out int a)
        {
            // ошибка компиляции - использование выходного параметра, которому не присвоено значение
            Console.WriteLine(a); 
            a = 2;
        }
Модификатор ref передает в метод ссылку на адрес переменной в памяти, соответственно мы перед использованием этого модификаторы должны обязательно проинициализировать переменную, т.е. указать адрес, на который она должна ссылаться. При этом внутри метода она ведет себя как обычный входной параметр (т.е. мы можем и не присваивать никакого значения данной переменной, а просто использовать его):
C#
1
2
3
4
5
6
7
8
9
        static void Main(string[] args)
        {
            int a=2;
            Meth(ref a);
        }
        static void Meth(ref int a)
        {
            Console.WriteLine(a);
        }
Но если значение будет присвоено, то это значение и будет присвоено переменной вне предела метода.

На уровне CLR для out- и ref-параметров используется один и тот же механизм. Соответственно мы не можем перегружать методы, только меняя модификатор ref на out и наоборот. Например, следующее, является перегрузкой, мы можем написать:
C#
1
2
    public void Method(int a) { }
    public void Method(out int a) { a = 1; }
Но мы не можем написать:
C#
1
2
    public void Method(out int a) { }
    public void Method(ref int a) { }
1
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
08.09.2016, 10:59

Делегаты. Ковариантность и контравариантность - какова их суть и назначение
Недавно пересматривал книгу шилдта, а именно делегаты, прочитал пример про ковариантность и...

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

Полиморфизм: ошибка преобразование типа из "ref cl_child" в "ref cl_proto" невозможно
Создал класс предок cl_proto, объявил класс потомок cl_child : cl_proto. Написал отдельную функцию...

Каковы суть и назначение #include <iomanip>
Подскажите новичку, что такое #include &lt;iomanip&gt; и для чего это надо? Только на понятном языке :D


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
14
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru