Blog Dla Młodszych Programistów C#/.NET

29 grudnia 2020
Koniec roku coraz bliżej, zastanawiałem się jakie tematy jeszcze warto poruszyć i jakie tematy mogą przynieść Ci drogi czytelniku najwięcej wartości. Wiem, że sporo z moich czytelników dopiero rozgląda się za pierwszą pracą, bierze udział w rozmowach kwalifikacyjnych, dlatego chyba warto poruszyć tematy, o które możesz zostać zapytany na swojej rozmowie kwalifikacyjnej. Niestety takich pytań jest sporo, w kolejnych artykułach przybliżę Ci kolejne, ale dzisiaj pokaże Ci jak w C# możesz przekazać zmienną typu prostego do metody za pomocą referencji. Oczywiście w tym celu będziemy musieli użyć słów kluczowych ref lub out i to właśnie w tym artykule pokaże Ci jak ich użyć oraz jakie są między nimi podstawowe różnice.

Ref vs Out Na Przykładach w C#


Jaki problem chcemy rozwiązać?


Załóżmy, że mamy prostą aplikację konsolową. W metodzie Main mamy najpierw inicjalizację zmiennej typu int o nazwie myNumber, a następnie wywołujemy 3 razy metodę IncrementValue, która powinna za każdym razem zwiększyć wartość naszej zmiennej o 1. Czyli taki kod, może wyglądać w ten sposób:
using System;

namespace Demo
{  
    class Program
    {
        static void Main()
        {
            int myNumber = 0;
            IncrementValue(myNumber);
            IncrementValue(myNumber);
            IncrementValue(myNumber);
            Console.WriteLine(myNumber);//0
        }

        public static void IncrementValue(int value)
        {
            value++;
        }
    }
}
Niestety nasza zmienna nie została zwiększona i nadal ma wartość 0. Dlaczego tak się stało? Zmienna myNumber jest typu int, a int jest typem prostym (typem wartościowym) i przez to, do metody IncrementValue została przekazana sama wartość zmiennej. W takim przypadku wartość zmiennej myNumber ciągle jest taka sama. Jak w takim razie za pomocą metody IncrementValue zwiększyć wartość zmiennej myNumber? Musimy do metody IncrementValue przekazać zmienną myNumber przez referencje. Aby to zrobić, musimy użyć słowa kluczowego ref lub out.


Jak użyć słowa kluczowego ref?


W sygnaturze metody IncrementValue musisz oznaczyć parametr słowem ref oraz przy wywołaniu tak samo musisz dodać słowo kluczowe ref.
using System;

namespace Demo
{  
    class Program
    {
        static void Main()
        {
            int myNumber = 0;
            IncrementValue(ref myNumber);
            IncrementValue(ref myNumber);
            IncrementValue(ref myNumber);
            Console.WriteLine(myNumber);//3
        }

        public static void IncrementValue(ref int value)
        {
            value++;
        }
    }
} 


Jak użyć słowa kluczowego out?


using System;

namespace Demo
{  
    class Program
    {
        static void Main()
        {
            int myNumber;
            IncrementValue(out myNumber);
            IncrementValue(out myNumber);
            IncrementValue(out myNumber);
            Console.WriteLine(myNumber);//11
        }

        public static void IncrementValue(out int value)
        {
            value = 10;
            value++;
        }
    }
}
Jak widzisz, w tym przypadku out nie ma zbyt dużego sensu, jednak możesz go użyć podobnie jak ref. To znaczy, gdy chcesz użyć słowa kluczowego out, to musisz oznaczyć parametr w sygnaturze tym słowem oraz przy wywołaniu metody również musisz argument poprzedzić słowem kluczowym out. Skoro inicjalizacja przed przekazaniem do metody jest zbędna, to również możesz wywołać metodę w ten sposób:
static void Main()
{
    IncrementValue(out int myNumber);
    Console.WriteLine(myNumber);
}


ref vs out – jaka jest różnica pomiędzy ref i out?


Jak na pewno zdążyłeś zauważyć, oba sposoby trochę się od siebie różnią, wynika to z tego, że każdy z nich będzie bardziej dopasowany do innej sytuacji. Podstawowe różnice pomiędzy nimi:
  • Zmienna oznaczona słowem ref musi być zainicjalizowana przed przekazaniem jej jako parametr. U nas: "int number = 0;".
  • Zmienna oznaczona słowem out nie musi (ale może) być zainicjalizowana przed przekazaniem jej jako parametr. U nas: "int number;". Również może być inicjalizacja przed przekazaniem, lecz nie ma to najmniejszego sensu.
  • Zmienna oznaczona przez ref nie musi zostać zainicjalizowana w metodzie. U nas dopuszczalny był sam zapis: "value++;".
  • Zmienna oznaczona przez out musi zostać zainicjalizowana w metodzie. U nas zmienna oprócz inkrementacji musiała najpierw zostać zainicjalizowana: "value = 10; value++;".


Który sposób, w jakiej sytuacji użyć?


Zmienna oznaczona przez ref mówi nam, że zmienna została już wcześniej zainicjalizowana i może zostać odczytana lub/i zmieniona w metodzie, a wszystkie zmiany będą widoczne również poza metodą. Zmienna oznaczona przez out mówi nam, że zmienna nie została jeszcze zainicjalizowana, nie ma żadnej wartości. Jej wartość będzie zainicjalizowana wewnątrz metody i zazwyczaj używamy w przypadkach, gdy chcemy, żeby wartość jakiejś zmiennej została zmieniona poza metodą.


PODSUMOWANIE


Także jak widzisz, mimo że ref i out z pozoru mają takie samo zastosowanie, to każde z nich będzie przydane w innej sytuacji. Ref używamy, gdy interesuje nas zarówno wartość zmiennej, która została nadana przed przekazaniem do metody, jak i wartość po wyjściu z tej metody, a out, gdy interesuje nas tylko wartość po wyjściu z metody (jak sama nazwa wskazuje). Jak wspomniałem na wstępie, takie pytanie może ukazać się na Twojej rozmowie kwalifikacyjnej na stanowisko młodszego programisty C#/.NET, jeżeli interesują Cię inne takie pytania, to daj znać w komentarzu. Możesz też zerknąć na dokument, w którym znajdziesz najczęstsze 10 pytań wraz z odpowiedziami, które miałem na rozmowach kwalifikacyjnych (dokument pdf), gdy szukałem pracy na stanowisku młodszego programisty C#.

Poprzedni artykuł - Czy Tak Naprawdę Znasz Różnice Pomiędzy First vs FirstOrDefault vs Single vs SingleOrDefault?.
Następny artykuł - Zanim Zaczniesz Programować – Instalacja i Zapoznanie z Visual Studio
Autor artykułu:
Kazimierz Szpin
Kazimierz Szpin
Programista C#/.NET. Głównie pisze aplikacje w ASP.NET MVC, WPF oraz Windows Forms. Specjalizuje się w testach jednostkowych.
Autor bloga ModestProgrammer.pl
Komentarze (2)
Łukasz
ŁUKASZ, 31 grudnia 2020 13:32
Lepiej unikać słowa ref - unikać błędów możliwego przypisania nieodpowiednich wartości, Lepiej używać słowa kluczowego in (+ dla sturktur readonly struct) dla bezpieczeństwa i optymalizacji.
Kazimierz Szpin
KAZIMIERZ SZPIN, 1 stycznia 2021 08:44
Cześć @ŁUKASZ. No tak, tylko słowo kluczowe in jest readonly i nie może zostać zmienione w metodzie.
Dodaj komentarz
© Copyright 2021 modestprogrammer.pl. Wszelkie prawa zastrzeżone. Polityka prywatności. Design by Kazimierz Szpin