Kiedy stosować in vs ref vs out


383

Ktoś zapytał mnie innego dnia, kiedy powinien użyć słowa kluczowego parametru outzamiast ref. Chociaż (myślę) rozumiem różnicę między słowami kluczowymi refi out(o które pytano wcześniej ), a najlepszym wyjaśnieniem wydaje się to, że ref== ini outjakie są niektóre (hipotetyczne lub kodowe) przykłady, w których zawsze powinienem używać, outa nie ref.

Ponieważ refjest bardziej ogólny, dlaczego kiedykolwiek chcesz używać out? Czy to tylko cukier syntaktyczny?


18
Zmienna przekazana przy użyciu outnie może zostać odczytana przed przypisaniem do niej. refnie ma tego ograniczenia. Więc to jest to.
Corey Ogburn,

17
W skrócie, refoznacza wejście / wyjście, natomiast parametr outjest tylko wyjściem.
Tim S.

3
Czego dokładnie nie dostajesz?
tnw

4
Również outzmienne MUSZĄ być przypisane w funkcji.
Corey Ogburn,

Dzięki, Corey. Ale ja już nie to. Chodzi mi o to, jaka jest z tego korzyść. Właściwie potrzebuję przykładu, który pokazuje scenariusz, w którym możemy użyć parametru ref, aby osiągnąć funkcjonalność, której nie można osiągnąć za pomocą parametru out i vice versa.
Rajbir Singh,

Odpowiedzi:


399

Powinieneś używać, outchyba że potrzebujesz ref.

To robi dużą różnicę, gdy dane muszą zostać zebrane, np. W innym procesie, który może być kosztowny. Dlatego chcesz uniknąć zbierania wartości początkowej, gdy metoda jej nie wykorzystuje.

Poza tym pokazuje czytelnikowi deklaracji lub wywołania, czy wartość początkowa jest istotna (i potencjalnie zachowana), czy wyrzucona.

Z niewielkiej różnicy parametr wyjściowy nie musi być inicjowany.

Przykład dla out:

string a, b;
person.GetBothNames(out a, out b);

gdzie GetBothNames to metoda atomowego pobierania dwóch wartości, metoda nie zmieni zachowania, niezależnie od tego, jakie są wartości aib. Jeśli połączenie zostanie wysłane do serwera na Hawajach, skopiowanie stąd początkowych wartości na Hawaje jest marnotrawstwem przepustowości. Podobny fragment przy użyciu ref:

string a = String.Empty, b = String.Empty;
person.GetBothNames(ref a, ref b);

może mylić czytelników, ponieważ wygląda na to, że początkowe wartości aib są istotne (chociaż nazwa metody wskazuje, że nie są).

Przykład dla ref:

string name = textbox.Text;
bool didModify = validator.SuggestValidName(ref name);

Tutaj wartość początkowa jest istotna dla metody.


5
„Tak nie jest.” - czy możesz lepiej wyjaśnić, co masz na myśli?
peterchen

3
Nie chcesz używać refwartości domyślnych.
C.Evenhuis

155
Dla potomnych: Jeszcze jedna różnica, o której nikt inny nie wspomniał, jak stwierdzono tutaj ; dla outparametru metoda wywołująca jest wymagana do przypisania wartości przed powrotem metody. - nie musisz nic robić z parametrem ref.
brichins,

3
@brichins Zapoznaj się z sekcją „komentarze (uzupełnienia społeczności)” we wspomnianym przez Ciebie łączu . Jest to błąd, który został poprawiony w dokumentacji VS 2008.
Bharat Ram V

13
@brichins wywoływana metoda jest wymagana do przypisania wartości, a nie metody wywołującej. zverev.eugene właśnie to poprawiono w dokumentacji VS 2008.
Segfault

72

Użyj out, aby zaznaczyć, że parametr nie jest używany, tylko ustaw. Pomaga to dzwoniącemu zrozumieć, że zawsze inicjujesz parametr.

Ponadto ref i out są nie tylko dla typów wartości. Pozwalają również zresetować obiekt, do którego odwołuje się typ odwołania z metody.


3
+1 Nie wiedziałem, że można go również stosować do typów referencyjnych, fajna jasna odpowiedź, dzięki
Dale

@brichins: Nie, nie możesz. outparametry są traktowane jako nieprzypisane przy wejściu do funkcji. Nie będziesz w stanie sprawdzić ich wartości, dopóki na pewno nie przypiszesz pewnej wartości - w ogóle nie ma możliwości użycia wartości, którą parametr miał w momencie wywołania funkcji.
Ben Voigt,

To prawda, że ​​nie można uzyskać dostępu do wartości przed przypisaniem wewnętrznym. Miałem na myśli to, że sam parametr może być później użyty w metodzie - nie jest zablokowany. To, czy rzeczywiście należy to zrobić, czy nie, to inna dyskusja (na temat projektu); Chciałem tylko zaznaczyć, że to możliwe. Dziękuję za wyjaśnienie.
brichins

2
@ ดาว: Można go używać z typami referencji, ponieważ przekazując parametr typu referencji, przekazuje się wartość referencji, a nie sam obiekt. Tak więc nadal jest przekazywana przez wartość.
Tarik

38

Masz rację, że semantycznie refzapewnia zarówno funkcję „ wejściową”, jak i „wyjściową”, podczas gdy outzapewnia tylko funkcję „wyjściową”. Jest kilka rzeczy do rozważenia:

  1. outwymaga, aby metoda akceptująca parametr MUSI w pewnym momencie przed zwróceniem przypisać wartość do zmiennej. Ten wzorzec znajduje się w niektórych klasach przechowywania danych kluczy / wartości, takich jak Dictionary<K,V>, gdzie masz funkcje, takie jak TryGetValue. Ta funkcja przyjmuje outparametr, który przechowuje wartość, która zostanie pobrana. To nie ma sensu dla rozmówcy przekazać wartość do tej funkcji, więc outjest stosowany w celu zagwarantowania, że niektóre wartość będzie w zmiennej po połączeniu, nawet jeśli nie jest to „prawdziwe” dane (w przypadku TryGetValuegdzie klucz nie jest obecny).
  2. outa refparametry są zmieniane w różny sposób w przypadku kodu interop

Nawiasem mówiąc, należy zauważyć, że chociaż typy referencyjne i typy wartości różnią się charakterem ich wartości, każda zmienna w Twojej aplikacji wskazuje na lokalizację pamięci, która przechowuje wartość , nawet dla typów referencyjnych. Zdarza się po prostu, że przy typach referencyjnych wartość zawarta w tym miejscu pamięci jest innalokalizacja pamięci. Gdy przekazujesz wartości do funkcji (lub wykonujesz dowolne inne przypisanie zmiennej), wartość tej zmiennej jest kopiowana do innej zmiennej. W przypadku typów wartości oznacza to, że cała zawartość typu jest kopiowana. Dla typów referencyjnych oznacza to, że lokalizacja pamięci jest kopiowana. Tak czy inaczej, tworzy kopię danych zawartych w zmiennej. Jedyne prawdziwe znaczenie, jakie ma to dotyczy semantyki przydziału; przy przypisywaniu zmiennej lub przekazywaniu przez wartość (domyślną), kiedy nowe przypisanie jest wprowadzane do oryginalnej (lub nowej) zmiennej, nie wpływa to na inną zmienną. W przypadku typów referencyjnych tak, zmiany wprowadzone w instancjisą dostępne po obu stronach, ale to dlatego, że rzeczywista zmienna jest tylko wskaźnikiem do innej lokalizacji pamięci; zawartość zmiennej - lokalizacja pamięci - w rzeczywistości się nie zmieniła.

Przekazywanie ze refsłowem kluczowym oznacza, że ​​zarówno oryginalna zmienna, jak i parametr funkcji faktycznie wskazują tę samą lokalizację pamięci. To znowu dotyczy tylko semantyki przypisania. Jeśli nowa wartość zostanie przypisana do jednej ze zmiennych, to ponieważ druga wskazuje na to samo miejsce w pamięci, nowa wartość zostanie odzwierciedlona po drugiej stronie.


1
Zauważ, że wymóg, aby wywoływana metoda przypisywała wartość do parametru wyjściowego, jest egzekwowany przez kompilator c #, a nie przez leżącą u jego podstaw IL. Tak więc biblioteka napisana w VB.NET może nie być zgodna z tą konwencją.
jmoreno

Wygląda na to, że ref jest w rzeczywistości odpowiednikiem symbolu dereferencji w C ++ (*). Referencyjne przekazywanie w języku C # musi być równoważne temu, co C / C ++ określa jako podwójne wskaźniki (wskaźnik do wskaźnika), więc odwołanie musi wyrejestrować pierwszy wskaźnik, umożliwiając wywoływanej metodzie dostęp do lokalizacji pamięci rzeczywistego obiektu w kontekście.
ComeIn

Właściwie sugerowałbym poprawne TryGetValueużycie, refa nie outwyraźne w przypadku nie znalezienia klucza.
NetMage,

27

Zależy to od kontekstu kompilacji (patrz przykład poniżej).

outi refoba oznaczają przekazywanie zmiennych przez referencję, ale refwymagają zainicjowania zmiennej przed przekazaniem, co może być istotną różnicą w kontekście Marshaling (Interop: UmanagedToManagedTransition lub odwrotnie)

MSDN ostrzega :

Nie należy mylić pojęcia przejścia przez odniesienie z pojęciem typów odniesienia. Te dwie koncepcje nie są takie same. Parametr metody można modyfikować przez odwołanie niezależnie od tego, czy jest to typ wartości, czy typ odniesienia. Nie ma boksu typu wartości, gdy jest przekazywany przez referencję.

Z oficjalnych dokumentów MSDN:

Słowo kluczowe out powoduje przekazanie argumentów przez odwołanie. Jest to podobne do słowa kluczowego ref, z tym wyjątkiem, że ref wymaga zainicjowania zmiennej przed przekazaniem

Słowo kluczowe ref powoduje przekazanie argumentu przez odwołanie, a nie przez wartość. Efektem przekazania przez referencję jest to, że każda zmiana parametru w metodzie jest odzwierciedlana w podstawowej zmiennej argumentu w metodzie wywołującej. Wartość parametru referencyjnego jest zawsze taka sama jak wartość bazowej zmiennej argumentowej.

Możemy sprawdzić, czy out i ref są rzeczywiście takie same, gdy argument zostanie przypisany:

Przykład CIL :

Rozważ następujący przykład

static class outRefTest{
    public static int myfunc(int x){x=0; return x; }
    public static void myfuncOut(out int x){x=0;}
    public static void myfuncRef(ref int x){x=0;}
    public static void myfuncRefEmpty(ref int x){}
    // Define other methods and classes here
}

w CIL instrukcje myfuncOuti myfuncRefsą identyczne jak oczekiwano.

outRefTest.myfunc:
IL_0000:  nop         
IL_0001:  ldc.i4.0    
IL_0002:  starg.s     00 
IL_0004:  ldarg.0     
IL_0005:  stloc.0     
IL_0006:  br.s        IL_0008
IL_0008:  ldloc.0     
IL_0009:  ret         

outRefTest.myfuncOut:
IL_0000:  nop         
IL_0001:  ldarg.0     
IL_0002:  ldc.i4.0    
IL_0003:  stind.i4    
IL_0004:  ret         

outRefTest.myfuncRef:
IL_0000:  nop         
IL_0001:  ldarg.0     
IL_0002:  ldc.i4.0    
IL_0003:  stind.i4    
IL_0004:  ret         

outRefTest.myfuncRefEmpty:
IL_0000:  nop         
IL_0001:  ret         

nop : brak operacji, ldloc : load local, stloc : stack local, ldarg : load argument, bs.s : branch to target ....

(Patrz: lista instrukcji CIL )


23

Poniżej znajduje się kilka notatek, które wyciągnąłem z tego artykułu kodowego na temat C # Out Vs Ref

  1. Należy go używać tylko wtedy, gdy oczekujemy wielu wyników od funkcji lub metody. Myśl o strukturach może być również dobrą opcją dla tego samego.
  2. REF i OUT to słowa kluczowe, które określają sposób przekazywania danych od osoby dzwoniącej do osoby odbierającej i odwrotnie.
  3. W REF dane przechodzą w dwie strony. Od dzwoniącego do dzwoniącego i odwrotnie.
  4. Dane wejściowe są przekazywane tylko w jedną stronę od odbiorcy do dzwoniącego. W takim przypadku, jeśli dzwoniący spróbuje wysłać dane do odbiorcy, zostanie on przeoczony / odrzucony.

Jeśli jesteś osobą wizualną, zobacz ten film na YouTube, który pokazuje różnicę praktycznie https://www.youtube.com/watch?v=lYdcY5zulXA

Poniższy obraz pokazuje różnice bardziej wizualnie

C # Out Vs Ref


1
one-way, two-waywarunki mogą być niewłaściwie użyte tutaj. W rzeczywistości oba są dwukierunkowe, jednak ich zachowania koncepcyjne różnią się w odniesieniu do odniesień i wartości parametrów
ibubi

17

Musisz użyć, refjeśli planujesz odczytywać i zapisywać parametry. Musisz użyć, outjeśli tylko planujesz pisać. W efekcie outma to miejsce, gdy potrzebujesz więcej niż jednej wartości zwracanej lub gdy nie chcesz używać normalnego mechanizmu zwracania danych wyjściowych (ale powinno to być rzadkie).

Istnieją mechanizmy językowe, które pomagają w tych przypadkach użycia. Refparametry muszą zostać zainicjowane, zanim zostaną przekazane do metody (kładąc nacisk na fakt, że są one do odczytu i zapisu), a outparametrów nie można odczytać przed przypisaniem wartości i gwarantuje się, że zostały zapisane na końcu metoda (nacisk kładziony na fakt, że są one tylko pisaniem). Naruszenie tych zasad powoduje błąd kompilacji.

int x;
Foo(ref x); // error: x is uninitialized

void Bar(out int x) {}  // error: x was not written to

Na przykład int.TryParsezwraca a booli akceptuje out intparametr:

int value;
if (int.TryParse(numericString, out value))
{
    /* numericString was parsed into value, now do stuff */
}
else
{
    /* numericString couldn't be parsed */
}

Jest to wyraźny przykład sytuacji, w której należy podać dwie wartości: wynik liczbowy i informację, czy konwersja zakończyła się powodzeniem, czy nie. Autorzy CLR postanowili wybrać outtutaj, ponieważ nie dbają o to, coint mogło być wcześniej.

Dla ref, można spojrzeć na Interlocked.Increment:

int x = 4;
Interlocked.Increment(ref x);

Interlocked.Incrementatomowo zwiększa wartość x. Ponieważ musisz czytać, xaby zwiększyć, jest to sytuacja, w której refjest bardziej odpowiednie. Zależy ci całkowicie na tym, co xbyło, zanim to zostało przekazaneIncrement .

W następnej wersji C # możliwe będzie nawet zadeklarowanie zmiennej w outparametrach, jeszcze większy nacisk na ich charakter tylko wyjściowy:

if (int.TryParse(numericString, out int value))
{
    // 'value' exists and was declared in the `if` statement
}
else
{
    // conversion didn't work, 'value' doesn't exist here
}

Dziękuję za odpowiedź. Ale czy możesz mi wyjaśnić, dlaczego nie mogłem wykorzystać do odczytu i zapisu parametru?
Rajbir Singh,

@RajbirSingh, ponieważ outparametry niekoniecznie zostały zainicjowane, więc kompilator nie pozwoli ci odczytać outparametru, dopóki coś do niego nie napiszesz .
zneak

zajrzeć, zgodziłem się z tobą. Ale w poniższym przykładzie parametr out może być użyty jako odczyt i zapis: string name = "myName"; private void OutMethod (out string nameOut) {if (nameOut == "myName") {nameOut = "Rajbir Singh metoda out"; }}
Rajbir Singh,

1
@RajbirSingh, twój przykład się nie kompiluje. Nie możesz przeczytać nameOutw swoim ifoświadczeniu, ponieważ wcześniej nie zostało mu to przypisane.
zneak

Dzięki @zneak. Masz absolutną rację. Nie kompiluje się.
Wielkie

7

out jest bardziej ograniczoną wersją ref .

W treści metody musisz przypisać wszystkie outparametry przed opuszczeniem metody. Również wartości przypisane do outparametru są ignorowane, natomiastref wymagają ich przypisania.

Więc outpozwala zrobić:

int a, b, c = foo(out a, out b);

gdzie refwymagałoby przypisania aib.


Jeśli cokolwiek, outto wersja mniej ograniczona. refma „Warunek: zmienna jest definitywnie przypisana, Warunek: zmienna jest definitywnie przypisana”, podczas gdy outma tylko „Warunek: zmienna jest definitywnie przypisana”. (I zgodnie z oczekiwaniami, potrzeba więcej implementacji funkcji z mniejszą liczbą warunków wstępnych)
Ben Voigt

@BenVoigt: Zgaduję, że to zależy w jakim kierunku patrzysz :) Myślę, że miałem na myśli ograniczenie w zakresie elastyczności kodowania (?).
leppie

7

Jak to brzmi:

z = tylko initialize / wypełnić parametr (parametr musi być pusty) odesłać go na zwykły

ref = wzorzec, standardowy parametr (może z wartością), ale funkcja może go modifiy.


nasza zmienna parametru może otrzymać wartość, zanim przekażesz ją do metody.
Bence Végert

6

Możesz użyć out kontekstowego słowa kluczowego w dwóch kontekstach (każdy jest linkiem do szczegółowych informacji), jako modyfikator parametru lub w deklaracjach parametrów typu ogólnego w interfejsach i delegatach. W tym temacie omówiono modyfikator parametrów, ale ten drugi temat zawiera informacje na temat deklaracji parametrów typu ogólnego.

Słowo outkluczowe powoduje przekazanie argumentów przez odwołanie. To jest jak refsłowo kluczowe, z tą różnicą, że refwymaga zainicjowania zmiennej przed jej przekazaniem. Aby użyć outparametru, zarówno definicja metody, jak i metoda wywołująca muszą jawnie używać outsłowa kluczowego. Na przykład: C #

class OutExample
{
    static void Method(out int i)
    {
        i = 44;
    }
    static void Main()
    {
        int value;
        Method(out value);
        // value is now 44
    }
}

Chociaż zmienne przekazane jako outargumenty nie muszą być inicjowane przed przekazaniem, wywoływana metoda jest wymagana do przypisania wartości przed jej zwróceniem.

Chociaż słowa kluczowe refi outpowodują różne zachowanie w czasie wykonywania, nie są one uważane za część sygnatury metody w czasie kompilacji. Dlatego metod nie można przeciążać, jeśli jedyną różnicą jest to, że jedna metoda przyjmuje refargument, a druga przyjmuje outargument. Na przykład następujący kod nie zostanie skompilowany: C #

class CS0663_Example
{
    // Compiler error CS0663: "Cannot define overloaded 
    // methods that differ only on ref and out".
    public void SampleMethod(out int i) { }
    public void SampleMethod(ref int i) { }
}

Przeciążenie można jednak wykonać, jeśli jedna metoda pobiera argument reflub, outa druga nie używa żadnego z nich, na przykład: C #

class OutOverloadExample
{
    public void SampleMethod(int i) { }
    public void SampleMethod(out int i) { i = 5; }
}

Właściwości nie są zmiennymi i dlatego nie mogą być przekazywane jako outparametry.

Aby uzyskać informacje o przekazywaniu tablic, zobacz Przekazywanie tablic przy użyciu refiout (Podręcznik programowania w języku C #).

Nie można używać słów kluczowych refi outdo następujących rodzajów metod:

Async methods, which you define by using the async modifier.

Iterator methods, which include a yield return or yield break statement.

Przykład

Zadeklarowanie outmetody jest przydatne, gdy metoda ma zwracać wiele wartości. W poniższym przykładzie użyto outdo zwrócenia trzech zmiennych za pomocą pojedynczego wywołania metody. Zauważ, że trzeci argument jest przypisany do null. Umożliwia to metodom opcjonalne zwracanie wartości. DO#

class OutReturnExample
{
    static void Method(out int i, out string s1, out string s2)
    {
        i = 44;
        s1 = "I've been returned";
        s2 = null;
    }
    static void Main()
    {
        int value;
        string str1, str2;
        Method(out value, out str1, out str2);
        // value is now 44
        // str1 is now "I've been returned"
        // str2 is (still) null;
    }
}

6

Jak używać inlub outczy refw C #?

  • Wszystkie słowa kluczowe C#mają tę samą funkcjonalność, ale z pewnymi granicami .
  • in Argumenty nie mogą być modyfikowane przez wywoływaną metodę.
  • ref argumenty mogą być modyfikowane.
  • ref musi zostać zainicjowany przed użyciem przez program wywołujący, można go odczytać i zaktualizować w metodzie.
  • out argumenty muszą zostać zmodyfikowane przez program wywołujący.
  • out argumenty muszą być inicjowane w metodzie
  • Zmienne przekazywane jako inargumenty muszą zostać zainicjowane przed przekazaniem w wywołaniu metody. Wywołana metoda może jednak nie przypisać wartości ani zmodyfikować argumentu.

Nie można używać in, refi outsłów kluczowych dla następujących rodzajów metod:

  • Metody asynchroniczne , które definiujesz za pomocą asyncmodyfikatora.
  • Metody iteratora , które zawierają instrukcję yield returnlub yield break.

5

Tylko w celu wyjaśnienia komentarza OP, że użycie przy ref i out jest „odniesieniem do typu wartości lub struktury zadeklarowanej poza metodą”, co zostało już ustalone niepoprawnie.

Rozważ użycie ref w StringBuilder, który jest typem referencyjnym:

private void Nullify(StringBuilder sb, string message)
{
    sb.Append(message);
    sb = null;
}

// -- snip --

StringBuilder sb = new StringBuilder();
string message = "Hi Guy";
Nullify(sb, message);
System.Console.WriteLine(sb.ToString());

// Output
// Hi Guy

W odniesieniu do tego:

private void Nullify(ref StringBuilder sb, string message)
{
    sb.Append(message);
    sb = null;
}

// -- snip --

StringBuilder sb = new StringBuilder();
string message = "Hi Guy";
Nullify(ref sb, message);
System.Console.WriteLine(sb.ToString());

// Output
// NullReferenceException

4

Argument przekazany jako ref musi zostać zainicjowany przed przekazaniem do metody, podczas gdy parametr out nie musi być zainicjowany przed przekazaniem do metody.


4

dlaczego kiedykolwiek chcesz to wykorzystać?

Aby poinformować innych, że zmienna zostanie zainicjowana, gdy powróci z wywołanej metody!

Jak wspomniano powyżej: „dla parametru wyjściowego metoda wywołująca jest wymagana do przypisania wartości przed powrotem metody ”.

przykład:

Car car;
SetUpCar(out car);
car.drive();  // You know car is initialized.

4

Zasadniczo obie refi outprzekazywania obiektu / wartość od metod

Słowo kluczowe out powoduje przekazanie argumentów przez odwołanie. To jest jak słowo kluczowe ref, z tym wyjątkiem, że ref wymaga zainicjowania zmiennej przed jej przekazaniem.

out : Argument nie został zainicjowany i musi zostać zainicjowany w metodzie

ref : Argument jest już zainicjowany i można go odczytać i zaktualizować w metodzie.

Jakie jest zastosowanie „ref” dla typów referencyjnych?

Możesz zmienić podane odwołanie na inną instancję.

Czy wiedziałeś?

  1. Chociaż słowa kluczowe ref i out powodują różne zachowanie w czasie wykonywania, nie są one uważane za część podpisu metody w czasie kompilacji. Dlatego metod nie można przeciążać, jeśli jedyną różnicą jest to, że jedna metoda przyjmuje argument ref, a druga przyjmuje argument out.

  2. Nie można używać słów kluczowych ref i out dla następujących rodzajów metod:

    • Metody asynchroniczne, które definiujesz za pomocą modyfikatora asynchronicznego.
    • Metody iteratora, które obejmują zwrot z zysku lub instrukcję podziału zysku.
  3. Właściwości nie są zmiennymi i dlatego nie mogą być przekazywane jako parametry wyjściowe.


4

Dodatkowe uwagi dotyczące C # 7:
W C # 7 nie ma potrzeby wcześniejszego określania zmiennych za pomocą out. Więc taki kod:

public void PrintCoordinates(Point p)
{
  int x, y; // have to "predeclare"
  p.GetCoordinates(out x, out y);
  WriteLine($"({x}, {y})");
}

Można napisać w ten sposób:

public void PrintCoordinates(Point p)
{
  p.GetCoordinates(out int x, out int y);
  WriteLine($"({x}, {y})");
}

Źródło: Co nowego w C # 7.


4

Nadal czuję potrzebę dobrego podsumowania, oto co wymyśliłem.

Podsumowanie,

Gdy znajdujemy się w funkcji , w ten sposób określamy zmienną kontrolę dostępu do danych,

in = R

out = musi W przed R

ref = R + W


Wyjaśnienie,

in

Funkcja może tylko CZYTAĆ tę zmienną.

out

Zmienna nie może być inicjowana jako pierwsza, ponieważ
funkcja MUSI ZAPISOWAĆ ją przed CZYTANIEM .

ref

Funkcja może ODCZYTAĆ / ZAPISOWAĆ do tej zmiennej.


Dlaczego tak się nazywa?

Koncentrując się na tym, gdzie dane są modyfikowane,

in

Dane należy ustawić tylko przed wejściem do (funkcji).

out

Dane należy ustawić tylko przed wyjściem z funkcji (out).

ref

Dane należy ustawić przed wejściem do (funkcji).
Dane mogą być ustawione przed opuszczeniem (wyjściem) funkcji.


być może (in / out / ref) należy zmienić nazwę na (r / wr / rw). a może nie, wejście / wyjście to ładniejsza metafora.
majsterkowicz

0

Należy zauważyć, że injest poprawnym słowem kluczowym od wersji C # 7.2 :

Modyfikator parametru in jest dostępny w wersji C # 7.2 i nowszych. Poprzednie wersje generowały błąd kompilatora CS8107 („Funkcja„ tylko do odczytu odniesienia ”nie jest dostępna w wersji C # 7.0. Proszę używać wersji językowej 7.2 lub nowszej.)) Aby skonfigurować wersję językową kompilatora, zobacz Wybór wersji językowej C #.

...

Słowo kluczowe in powoduje przekazanie argumentów przez referencję. To sprawia, że ​​parametr formalny jest aliasem dla argumentu, który musi być zmienną. Innymi słowy, każda operacja na parametrze jest wykonywana na argumencie. Przypomina słowa kluczowe ref lub out, tyle że w argumentach nie można modyfikować wywoływaną metodą. Podczas gdy argumenty ref mogą być modyfikowane, nasze argumenty muszą być modyfikowane przez wywoływaną metodę, a modyfikacje te można zaobserwować w kontekście wywołującym.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.