Jaka jest różnica między słowami kluczowymi " ref " i "out"?

Tworzę funkcję, w której muszę przekazać obiekt, aby mógł być modyfikowany przez funkcję. Jaka jest różnica między:

public void myFunction(ref MyClass someClass)

I

public void myFunction(out MyClass someClass)

Z czego korzystać i dlaczego?

Author: TK., 2008-12-23

26 answers

ref mówi kompilatorowi, że obiekt został zainicjowany przed wprowadzeniem funkcji, podczas gdy out mówi kompilatorowi, że obiekt zostanie zainicjowany wewnątrz funkcji.

Więc podczas gdy ref jest dwukierunkowe, {[1] } jest tylko out.

 1197
Author: Rune Grimstad,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-12-21 13:54:43

Modyfikator ref oznacza, że:

  1. wartość jest już ustawiona i
  2. metoda może ją odczytywać i modyfikować.

Modyfikator out oznacza, że:

  1. wartość nie jest ustawiona i nie może być odczytana metodą dopóki nie zostanie ustawiona.
  2. metoda musi ustawić ją przed powrotem.
 559
Author: Anton Kolesov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-21 00:19:40

Powiedzmy, że Dom pojawia się w boksie Petera w sprawie notatki o raportach TPS.

Gdyby Dom był argumentem ref, miałby wydrukowaną kopię notatki.

Gdyby Dom był argumentem, zmusiłby Petera do wydrukowania nowej kopii notatki, którą mógłby zabrać ze sobą.

 149
Author: Michael Blackburn,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-29 14:48:13

Spróbuję swoich sił w wyjaśnieniu:

Myślę, że rozumiemy, jak typy wartości działają dobrze? Typy wartości to (int, long, struct itd.). Gdy wysyłasz je do funkcji bez polecenia ref, kopiuje ona Dane. Wszystko, co zrobisz z tymi danymi w funkcji, wpływa tylko na kopię, nie na oryginał. Polecenie ref wysyła rzeczywiste dane i wszelkie zmiany będą miały wpływ na dane poza funkcją.

Ok Na części mylące, odniesienia rodzaje:

Stwórzmy Typ odniesienia:

List<string> someobject = new List<string>()

Gdy pojawi się nowy jakiś obiekt , powstają dwie części:

  1. blok pamięci przechowujący dane dla someobject.
  2. odniesienie (wskaźnik) do tego bloku danych.

Teraz Kiedy wysyłasz someobject do metody bez ref kopiuje referencję Wskaźnik, a nie dane. Więc teraz masz to:

(outside method) reference1 => someobject
(inside method)  reference2 => someobject

Dwa odniesienia wskazujące na to samo obiekt. Jeśli zmodyfikujesz właściwość someobject używając reference2, wpłynie to na te same dane, na które wskazuje reference1.

 (inside method)  reference2.Add("SomeString");
 (outside method) reference1[0] == "SomeString"   //this is true

Jeśli anulujesz reference2 lub wskażesz nowe dane, nie wpłynie to na reference1 ani na reference1.

(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true

The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject

Co się stanie, gdy wyślesz jakiś obiekt przez ref do metody? rzeczywiste odniesienie do someobject jest wysyłane do metody. Więc teraz masz tylko jedno odniesienie do data:

(outside method) reference1 => someobject;
(inside method)  reference1 => someobject;
Ale co to znaczy? Działa dokładnie tak samo jak wysyłanie someobject nie przez ref z wyjątkiem dwóch głównych rzeczy:

1) gdy zerujesz referencję wewnątrz metody, to zerujesz referencję spoza metody.

 (inside method)  reference1 = null;
 (outside method) reference1 == null;  //true

2) możesz teraz wskazać odniesienie do zupełnie innej lokalizacji danych, a odniesienie poza funkcją będzie teraz wskazywać nową lokalizację danych.

 (inside method)  reference1 = new List<string>();
 (outside method) reference1.Count == 0; //this is true
 60
Author: James Roland,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-23 17:55:58

Ref jest w i na zewnątrz .

Powinieneś używać out w preferencjach wszędzie tam, gdzie jest to wystarczające dla Twoich wymagań.

 30
Author: Ruben Bartelink,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-08-13 11:50:42

Out:

W C# metoda może zwracać tylko jedną wartość. Jeśli chcesz zwrócić więcej niż jedną wartość, możesz użyć słowa kluczowego out. Modyfikator out zwraca jako return-by-reference. Najprostszą odpowiedzią jest to, że słowo kluczowe " out " jest używane do uzyskania wartości z metody.

  1. nie musisz inicjalizować wartości w funkcji wywołującej.
  2. musisz przypisać wartość w wywołanej funkcji, w przeciwnym razie kompilator zgłosi błąd.

Ref:

W C#, kiedy przekazujesz typ wartości, taki jak int, float, double itp. jako argument do parametru metody jest przekazywana przez wartość. Dlatego, jeśli zmodyfikujesz wartość parametru, nie wpłynie to na argument w wywołaniu metody. Ale jeśli zaznaczysz parametr słowem kluczowym "ref", będzie on odzwierciedlał w rzeczywistej zmiennej.

  1. musisz zainicjalizować zmienną przed wywołaniem funkcji.
  2. nie jest obowiązkowe przypisywanie wartości do parametru ref w metodzie. Jeśli nie zmienisz wartość, jaka jest potrzeba, aby oznaczyć go jako "ref"?
 19
Author: Nazmul Hasan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-01 18:31:04

Rozszerzenie przykładu Pies, Kot. Druga metoda z ref zmienia obiekt, do którego odwołuje się wywołujący. Stąd "Kot" !!!

    public static void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog". 
        Bar(ref myObject);
        Console.WriteLine(myObject.Name); // Writes "Cat". 
    }

    public static void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

    public static void Bar(ref MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }
 13
Author: BBB,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-13 16:01:05

Ponieważ przekazujesz Typ odniesienia (klasę), nie ma potrzeby używania ref, ponieważ domyślnie przekazywana jest tylko Referencja do rzeczywistego obiektu i dlatego zawsze zmieniasz obiekt za referencją.

Przykład:

public void Foo()
{
    MyClass myObject = new MyClass();
    myObject.Name = "Dog";
    Bar(myObject);
    Console.WriteLine(myObject.Name); // Writes "Cat".
}

public void Bar(MyClass someObject)
{
    someObject.Name = "Cat";
}

Dopóki zdasz klasę, nie musisz używać ref, jeśli chcesz zmienić obiekt wewnątrz swojej metody.

 8
Author: Albic,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-23 10:57:23

ref i out zachowują się podobnie z wyjątkiem następujących różnic.

  • ref zmienna musi być zainicjalizowana przed użyciem. out zmienna może być używana bez przypisania
  • out parametr musi być traktowany jako niepodpisana wartość przez funkcję, która go używa. Możemy więc użyć inicjalizowanego parametru out w kodzie wywołującym, ale wartość zostanie utracona podczas wykonywania funkcji.
 8
Author: gmail user,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-02-10 16:29:27

Dla tych, którzy uczą się na przykładzie (jak ja) oto, co mówi Anthony Kolesov .

Stworzyłem kilka minimalnych przykładów ref, out i innych, aby zilustrować punkt. Nie zajmuję się najlepszymi praktykami, tylko przykładami, aby zrozumieć różnice.

Https://gist.github.com/2upmedia/6d98a57b68d849ee7091

 8
Author: 2upmedia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:18:28

Ref oznacza, że wartość w parametrze ref jest już ustawiona, metoda może ją odczytać i zmodyfikować. Użycie słowa kluczowego ref jest tym samym, co stwierdzenie, że wywołujący jest odpowiedzialny za inicjalizację wartości parametru.


Out mówi kompilatorowi, że za inicjalizację obiektu odpowiada funkcja, funkcja musi przypisać do parametru out. Nie wolno go zostawiać bez przydziału.

 7
Author: Farhan S.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-31 09:25:35

"Piekarz"

To dlatego, że pierwszy z nich zmienia Twój string-reference na point to "Baker". Zmiana referencji jest możliwa, ponieważ przekazałeś ją za pomocą słowa kluczowego ref (=>odniesienie do odniesienia do łańcucha znaków). Drugie wywołanie otrzymuje kopię odniesienia do łańcucha znaków.

String wygląda na coś specjalnego na początku. Ale string jest tylko klasą referencyjną i jeśli zdefiniujesz

string s = "Able";

Wtedy s jest odniesieniem do klasy string, która zawiera tekst "Able"! Inny przypisanie do tej samej zmiennej za pomocą

s = "Baker";

Nie zmienia oryginalnego ciągu znaków, lecz tworzy nową instancję i niech s wskaże na tę instancję!

Możesz go wypróbować za pomocą poniższego przykładowego kodu:

string s = "Able";
string s2 = s;
s = "Baker";
Console.WriteLine(s2);
Czego się spodziewałeś? To, co otrzymasz, jest nadal "Able", ponieważ po prostu ustawisz referencję w s na inną instancję, podczas gdy s2 wskazuje na oryginalną instancję.

Edytuj: string jest również niezmienny, co oznacza, że po prostu nie ma metody lub właściwości, które modyfikuje istniejącą instancję string (można spróbować znaleźć taką w dokumentach, ale nie będzie żadnej: -)). Wszystkie metody manipulacji łańcuchami zwracają nową instancję łańcuchów! (Dlatego często uzyskujesz lepszą wydajność podczas korzystania z klasy StringBuilder)

 6
Author: mmmmmmmm,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-12-23 13:45:33

Out: Instrukcja return może być używana do zwracania tylko jednej wartości z funkcji. Jednak za pomocą parametrów wyjściowych można zwrócić dwie wartości z funkcji. Parametry wyjściowe są jak parametry referencyjne, z tym wyjątkiem, że przesyłają dane z metody, a nie do niej.

Ilustruje to następujący przykład:

using System;

namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void getValue(out int x )
      {
         int temp = 5;
         x = temp;
      }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;

         Console.WriteLine("Before method call, value of a : {0}", a);

         /* calling a function to get the value */
         n.getValue(out a);

         Console.WriteLine("After method call, value of a : {0}", a);
         Console.ReadLine();

      }
   }
}

Ref: Parametr odniesienia jest odniesieniem do lokalizacji pamięci zmiennej. Gdy przekazujesz parametry przez odniesienie, w przeciwieństwie do parametry wartości, dla tych parametrów nie jest tworzona nowa lokalizacja magazynu. Parametry referencyjne reprezentują tę samą lokalizację pamięci, co rzeczywiste parametry, które są dostarczane do metody.

W C# deklarujesz parametry referencyjne używając słowa kluczowego ref. Ilustruje to poniższy przykład:

using System;
namespace CalculatorApplication
{
   class NumberManipulator
   {
      public void swap(ref int x, ref int y)
      {
         int temp;

         temp = x; /* save the value of x */
         x = y;   /* put y into x */
         y = temp; /* put temp into y */
       }

      static void Main(string[] args)
      {
         NumberManipulator n = new NumberManipulator();
         /* local variable definition */
         int a = 100;
         int b = 200;

         Console.WriteLine("Before swap, value of a : {0}", a);
         Console.WriteLine("Before swap, value of b : {0}", b);

         /* calling a function to swap the values */
         n.swap(ref a, ref b);

         Console.WriteLine("After swap, value of a : {0}", a);
         Console.WriteLine("After swap, value of b : {0}", b);

         Console.ReadLine();

      }
   }
}
 5
Author: Faisal Naseer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-10-25 16:57:43

Dla szukających zwięzłej odpowiedzi.

Zarówno ref jak i out Słowa kluczowe są używane do przekazywania - reference.


Zmienna słowa kluczowego ref musi mieć wartość lub musi odnosić się do obiektu lub null przed jej przemijaniem.


W przeciwieństwie do ref, zmienna słowa kluczowego out musi mieć wartość lub musi odnoszą się do obiektu lub null po jego przemijaniu, jak również nie ma potrzeby aby mieć wartość lub odwoływać się do obiektu przed mijam.

 5
Author: snr,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-26 07:49:35

Ref i out działają tak jak przekazywanie referencji i przekazywanie wskaźników jak w C++.

Dla ref, argument musi być zadeklarowany i zainicjalizowany.

Dla out, argument musi być zadeklarowany, ale może lub nie może być zainicjalizowany

        double nbr = 6; // if not initialized we get error
        double dd = doit.square(ref nbr);

        double Half_nbr ; // fine as passed by out, but inside the calling  method you initialize it
        doit.math_routines(nbr, out Half_nbr);
 4
Author: RotatingWheel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-03-15 10:36:25

Czas Tworzenia:

(1) tworzymy metodę wywołującą Main()

(2) tworzy obiekt List (który jest obiektem typu referencyjnego) i przechowuje go w zmiennej myList.

public sealed class Program 
{
    public static Main() 
    {
        List<int> myList = new List<int>();

Podczas Trwania:

(3) Runtime przydziela pamięć na stosie o numerze #00, wystarczająco szeroką, aby zapisać adres (#00 = myList, ponieważ nazwy zmiennych są tak naprawdę tylko aliasami dla Miejsc Pamięci)

(4) Runtime tworzy obiekt list na stercie w Miejscu Pamięci #FF( wszystkie te adresy są dla przykładu)

(5) Runtime przechowuje adres startowy # FF obiektu na # 00 (lub w słowach przechowuje odniesienie do obiektu List w wskaźniku myList)

Powrót do czasu tworzenia:

(6) Następnie przekazujemy obiekt List jako argument myParamList do wywołanej metody modifyMyList i przypisujemy do niego nowy obiekt List

List<int> myList = new List<int>();

List<int> newList = ModifyMyList(myList)

public List<int> ModifyMyList(List<int> myParamList){
     myParamList = new List<int>();
     return myParamList;
}

Podczas Trwania:

(7) Runtime uruchamia procedurę wywołania wywołanej metody i w jego ramach sprawdza rodzaj parametrów.

(8) Po znalezieniu typu odniesienia przydziela on pamięć na stosie o numerze #04 do aliasowania zmiennej parametru myParamList.

(9) zapisuje w nim również wartość #FF.

(10) Runtime tworzy obiekt list na stercie w Miejscu Pamięci #004 i zastępuje #FF W # 04 tą wartością (lub dereferuje oryginalny obiekt List i wskazuje na nowy obiekt List w tej metodzie)

Adres w #00 nie jest zmieniany i zachowuje odniesienie do #FF (lub oryginalny wskaźnik myList nie jest zakłócony).


The ref keyword jest dyrektywą kompilatora, która pomija generowanie kodu uruchomieniowego dla (8) i (9), co oznacza, że nie będzie alokacji Sterty Dla parametrów metody. Użyje oryginalnego wskaźnika # 00 do operowania na obiekcie w # FF. Jeśli oryginalny wskaźnik nie jest zainicjowany, runtime przestanie narzekać, że nie może kontynuować, ponieważ zmienna nie jest initialized

The out keyword jest dyrektywą kompilatora, która jest prawie taka sama jak ref z niewielką modyfikacją w (9) i (10). Kompilator oczekuje, że argument nie zostanie zainicjalizowany i będzie kontynuował za pomocą (8), (4) i (5) Tworzenie obiektu na stercie i zapisywanie jego adresu początkowego w zmiennej argumentu. Żaden niezainicjowany błąd nie zostanie wyrzucony, a wszelkie poprzednie odniesienia zapisane zostaną utracone.

 4
Author: supi,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-20 09:12:55

Oprócz możliwości przypisania cudzej zmiennej do innej instancji klasy, zwracania wielu wartości itp., za pomocą ref lub out pozwala komuś innemu dowiedzieć się, czego od nich potrzebujesz i co zamierzasz zrobić ze zmienną, którą dostarczają

  • You don ' t need ref lub out jeśli wszystko co zamierzasz zrobić to zmodyfikować wewnątrz instancji MyClass przekazywanej w argumencie someClass.

    • metoda wywołująca zobaczą zmiany takie jak someClass.Message = "Hello World" czy używasz ref, out or nothing
    • zapis someClass = new MyClass() wewnątrz myFunction(someClass) zamienia obiekt widziany przez someClass tylko w zakresie metody myFunction. Metoda wywołująca nadal wie o oryginalnej instancji MyClass, którą utworzyła i przekazała do Twojej metody
  • You need ref lub out jeśli planujesz zamienić someClass na zupełnie nowy obiekt i chcesz, aby metoda wywołująca zobaczyła Twoją zmianę

    • pisanie someClass = new MyClass() wewnątrz myFunction(out someClass) zmienia obiekt widziany metodą, która wywołała myFunction

Istnieją inni programiści

I chcą wiedzieć, co zrobisz z ich danymi. Wyobraź sobie, że piszesz bibliotekę, która będzie używana przez miliony programistów. Chcesz, aby wiedzieli, co zrobisz z ich zmiennymi, gdy wywołają Twoje metody]}
  • Użycie ref sprawia, że instrukcja " Pass zmiennej przypisanej do pewnej wartości podczas wywołania moja metoda. Należy pamiętać, że mogę zmienić go na coś zupełnie innego w trakcie mojej metody. Nie oczekuj, że Twoja zmienna będzie wskazywać na stary obiekt, gdy skończę"

  • Użycie out sprawia, że polecenie " podaj zmienną zastępczą do mojej metody. Nie ma znaczenia, czy ma wartość, czy nie; kompilator zmusi mnie do przypisania jej do nowej wartości. Absolutnie gwarantuję, że obiekt wskazywany przez zmienną przed wywołaniem mojej metody, will be different zanim skończę

Swoją drogą, w C#7.2 jest też in modyfikator

I to zapobiega zamianie przez metodę przekazanej instancji na inną instancję. Pomyśl o tym tak, jakby powiedzieć milionom programistów "podaj mi swoje oryginalne odniesienie do zmiennych, a obiecuję, że nie zamienię starannie przygotowanych danych na coś innego". in ma pewne cechy szczególne, a w niektórych przypadkach, na przykład, gdy Ukryty konwersja może być wymagana, aby twój Skrót był kompatybilny z in int kompilator tymczasowo utworzy int, rozszerzy Twój skrót do niego, przekaże go przez odniesienie i zakończy. Może to zrobić, ponieważ zadeklarowałeś, że nie będziesz z tym zadzierać.


Microsoft zrobił to za pomocą metod .TryParse na typach liczbowych:
int i = 98234957;
bool success = int.TryParse("123", out i);

Oznaczając parametr jako out aktywnie deklarują tutaj "jesteśmy zdecydowanie zamierzamy zmienić twoje wartość 98234957 na coś innego "

Oczywiście, w pewnym sensie muszą, dla rzeczy takich jak parsowanie typów wartości, ponieważ gdyby metoda parse nie mogła zamienić typu wartości na coś innego, nie działałoby to zbyt dobrze.. Ale wyobraź sobie, że istnieje jakaś fikcyjna metoda w jakiejś bibliotece, którą tworzysz: {]}

public void PoorlyNamedMethod(out SomeClass x)

Możesz zobaczyć, że jest to out, a zatem możesz wiedzieć, że jeśli spędzasz godziny na chrupaniu liczb, tworząc idealną Someklasę:

SomeClass x = SpendHoursMakingMeAPerfectSomeClass();
//now give it to the library
PoorlyNamedMethod(out x);

Cóż, to był strata czasu, tyle godzin, żeby zrobić te doskonałe zajęcia. Na pewno zostanie wyrzucony i zastąpiony przez PoorlyNamedMethod]}

 3
Author: Caius Jard,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-08-14 14:52:33

Aby zilustrować wiele doskonałych wyjaśnień, opracowałem następującą aplikację konsolową:]}

using System;
using System.Collections.Generic;

namespace CSharpDemos
{
  class Program
  {
    static void Main(string[] args)
    {
      List<string> StringList = new List<string> { "Hello" };
      List<string> StringListRef = new List<string> { "Hallo" };

      AppendWorld(StringList);
      Console.WriteLine(StringList[0] + StringList[1]);

      HalloWelt(ref StringListRef);
      Console.WriteLine(StringListRef[0] + StringListRef[1]);

      CiaoMondo(out List<string> StringListOut);
      Console.WriteLine(StringListOut[0] + StringListOut[1]);
    }

    static void AppendWorld(List<string> LiStri)
    {
      LiStri.Add(" World!");
      LiStri = new List<string> { "¡Hola", " Mundo!" };
      Console.WriteLine(LiStri[0] + LiStri[1]);
    }

    static void HalloWelt(ref List<string> LiStriRef)
     { LiStriRef = new List<string> { LiStriRef[0], " Welt!" }; }

    static void CiaoMondo(out List<string> LiStriOut)
     { LiStriOut = new List<string> { "Ciao", " Mondo!" }; }
   }
}
/*Output:
¡Hola Mundo!
Hello World!
Hallo Welt!
Ciao Mondo!
*/
  • AppendWorld: przekazywana jest kopia StringList o nazwie LiStri. Na początek metody, kopia ta odwołuje się do oryginalnej listy i dlatego może być używany do modyfikowania tej listy. Później {[3] } kolejny List<string> obiekt wewnątrz metody, który nie wpływa oryginalna lista.

  • HalloWelt: LiStriRef jest aliasem już zainicjowanego ListStringRef. Przekazywany obiekt List<string> jest służy do inicjalizacji nowy, zatem ref był konieczny.

  • CiaoMondo: LiStriOut jest aliasem ListStringOut i musi być zainicjowany.

Tak więc, jeśli metoda tylko modyfikuje obiekt, do którego odwołuje się przekazana zmienna, kompilator nie pozwoli Ci używać out i nie powinieneś używać ref, ponieważ to myliłoby nie kompilator, ale czytnik kodu. Jeśli metoda sprawi, że przekazany argument odwoła się do innego obiektu, użyj ref dla już zainicjowanego object i out dla metod, które muszą zainicjalizować nowy obiekt dla przekazanego argumentu. Poza tym ref i out zachowują się tak samo.

 3
Author: Dietrich Baumgarten,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-10-10 09:52:27

Są prawie takie same - jedyna różnica polega na tym, że zmienna przekazywana jako parametr wyjściowy nie musi być inicjalizowana, a metoda wykorzystująca parametr ref musi ją ustawić na coś.

int x;    Foo(out x); // OK 
int y;    Foo(ref y); // Error

Parametry Ref są dla danych, które mogą być modyfikowane, parametry out są dla danych, które są dodatkowym wyjściem dla funkcji (np int.TryParse), które już używają wartości zwracanej dla czegoś.

 2
Author: Talha Khan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-20 16:06:52

Ref: Słowo kluczowe ref jest używane do przekazania argumentu jako referencji. To znaczy, że gdy wartość tego parametru zostanie zmieniona w metodzie, zostanie ona odzwierciedlona w wywołującej metodzie. Argument przekazywany za pomocą słowa kluczowego ref musi zostać zainicjowany w wywołującej metodzie, zanim zostanie przekazany do wywołanej metody.

Out: Słowo kluczowe out jest również używane do przekazania argumentu, takiego jak słowo kluczowe ref, ale argument może być przekazany Bez przypisywania mu żadnej wartości. Argument przekazywany za pomocą słowo kluczowe out musi być zainicjalizowane w wywołanej metodzie, zanim powróci do wywołania metody.

public class Example
{
 public static void Main() 
 {
 int val1 = 0; //must be initialized 
 int val2; //optional

 Example1(ref val1);
 Console.WriteLine(val1); 

 Example2(out val2);
 Console.WriteLine(val2); 
 }

 static void Example1(ref int value) 
 {
 value = 1;
 }
 static void Example2(out int value) 
 {
 value = 2; 
 }
}

/* Output     1     2     

Ref i out w metodzie przeciążenia

Zarówno ref jak i out nie mogą być używane jednocześnie w przeciążeniu metody. Jednak ref i out są traktowane inaczej w czasie wykonywania, ale są traktowane tak samo w czasie kompilacji (CLR nie rozróżnia tych dwóch podczas tworzenia IL dla ref i out).

 2
Author: Dejan Ciev,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-26 23:22:38

Poniżej pokazałem przykład z użyciem obu Ref i out. Teraz wszyscy będziecie oczyszczeni z zarzutów.

W poniższym przykładzie gdy komentuję / / myRefObj = new myClass { Name = " ref Na Zewnątrz wywołane!! " }; line, pojawi się błąd mówiący "Use of unassigned local variable 'myRefObj '" , ale nie ma takiego błędu w out.

Gdzie użyć Ref : gdy wywołujemy procedurę z parametrem in i tym samym parametr zostanie użyty do przechowywania danych wyjściowych tego proc.

Where to use Out: gdy wywołujemy procedurę bez parametru in i ten sam param zostanie użyty do zwrócenia wartości z tego proc. Zwróć również uwagę na wyjście

public partial class refAndOutUse : System.Web.UI.Page
{
    protected void Page_Load(object sender, EventArgs e)
    {
        myClass myRefObj;
        myRefObj = new myClass { Name = "ref outside called!!  <br/>" };
        myRefFunction(ref myRefObj);
        Response.Write(myRefObj.Name); //ref inside function

        myClass myOutObj;
        myOutFunction(out myOutObj);
        Response.Write(myOutObj.Name); //out inside function
    }

    void myRefFunction(ref myClass refObj)
    {
        refObj.Name = "ref inside function <br/>";
        Response.Write(refObj.Name); //ref inside function
    }
    void myOutFunction(out myClass outObj)
    {
        outObj = new myClass { Name = "out inside function <br/>" }; 
        Response.Write(outObj.Name); //out inside function
    }
}

public class myClass
{
    public string Name { get; set; }
} 
 1
Author: Ankur Bhutani,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-10-29 15:45:22
 public static void Main(string[] args)
    {
        //int a=10;
        //change(ref a);
        //Console.WriteLine(a);
        // Console.Read();

        int b;
        change2(out b);
        Console.WriteLine(b);
        Console.Read();
    }
    // static void change(ref int a)
    //{
    //    a = 20;
    //}

     static void change2(out int b)
     {
         b = 20;
     }

Możesz sprawdzić ten kod, który opisze ci jego całkowitą różnicę kiedy używasz "ref" oznacza to, że u już zainicjalizujesz ten int / string

Ale kiedy używasz " out" działa w obu warunkach whather u initialize that int / string or not ale u musi zainicjalizować ten int / string w tej funkcji

 1
Author: Haris Zia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-13 11:01:16

Z punktu widzenia metody, która otrzymuje parametr, różnica między ref i out jest taka, że C# wymaga, aby metody zapisywały każdy parametr out przed powrotem i nie mogą wykonywać niczego z takim parametrem, poza przekazaniem go jako parametr out lub zapisaniem do niego, dopóki nie zostanie przekazany jako parametr out do innej metody lub napisany bezpośrednio. Zauważ, że niektóre inne języki nie nakładają takich wymagań; metoda wirtualna lub interfejs, który jest zadeklarowany w C# z parametrem out może być nadpisany w innym języku, który nie nakłada żadnych specjalnych ograniczeń na takie parametry.

Z punktu widzenia wywołującego, C# w wielu okolicznościach zakłada, że wywołanie metody z parametrem out spowoduje, że przekazana zmienna zostanie zapisana bez uprzedniego odczytu. To założenie może nie być poprawne podczas wywoływania metod napisanych w innych językach. Na przykład:

struct MyStruct
{
   ...
   myStruct(IDictionary<int, MyStruct> d)
   {
     d.TryGetValue(23, out this);
   }
}

Jeśli myDictionary identyfikuje IDictionary<TKey,TValue> implementacja napisana w języku innym niż C#, mimo że MyStruct s = new MyStruct(myDictionary); wygląda jak zadanie, może potencjalnie pozostawić s niezmodyfikowaną.

Zauważ, że konstruktory napisane w VB.NET w przeciwieństwie do tych w C#, nie należy zakładać, czy wywołane metody będą modyfikować dowolne parametry out i czyścić wszystkie pola bezwarunkowo. Dziwne zachowanie nawiązujące do powyższego nie wystąpi z kodem napisanym całkowicie w VB lub całkowicie w C#, ale może wystąpić, gdy kod napisany w C# wywoła a metoda napisana w VB.NET.

 0
Author: supercat,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-02-11 22:51:21

Jeśli chcesz przekazać swój parametr jako ref, powinieneś go zainicjować przed przekazaniem parametru do funkcji else kompilator sam pokaże błąd.Ale w przypadku out parametr nie trzeba inicjalizować parametr obiektu przed przekazaniem go do metody.Obiekt można zainicjować w samej wywołującej go metodzie.

 0
Author: Rakeshkumar Das,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-12-05 09:57:33

Należy pamiętać, że parametr odniesienia przekazywany wewnątrz funkcji jest bezpośrednio przetwarzany.

Na przykład,

    public class MyClass
    {
        public string Name { get; set; }
    }

    public void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog".
    }

    public void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

To napisze pies, nie Kot. Dlatego powinieneś bezpośrednio pracować nad someObject.

 -3
Author: Mangesh Pimpalkar,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-07-26 20:30:27

Może nie jestem w tym zbyt dobry, ale z pewnością ciągi (mimo że są technicznie typami referencyjnymi i żyją na stercie) są przekazywane przez wartość, a nie referencję?

        string a = "Hello";

        string b = "goodbye";

        b = a; //attempt to make b point to a, won't work.

        a = "testing";

        Console.WriteLine(b); //this will produce "hello", NOT "testing"!!!!

Dlatego potrzebujesz ref jeśli chcesz, aby zmiany istniały poza zakresem tworzonej funkcji, nie przekazujesz referencji w inny sposób.

O ile wiem, potrzebujesz tylko ref dla struktur / typów wartości i samego ciągu znaków, ponieważ string jest typem odniesienia, który udaje, że jest, ale nie jest wartością Typ.

Mogę się tu całkowicie mylić, jestem nowy.
 -4
Author: Edwin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-08 18:36:51