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?
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.
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:
- wartość jest już ustawiona i
- metoda może ją odczytywać i modyfikować.
Modyfikator out
oznacza, że:
- wartość nie jest ustawiona i nie może być odczytana metodą dopóki nie zostanie ustawiona.
- metoda musi ustawić ją przed powrotem.
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ą.
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:
- blok pamięci przechowujący dane dla someobject.
- 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
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
Powinieneś używać out
w preferencjach wszędzie tam, gdzie jest to wystarczające dla Twoich wymagań.
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.
- nie musisz inicjalizować wartości w funkcji wywołującej.
- 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.
- musisz zainicjalizować zmienną przed wywołaniem funkcji.
- 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"?
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;
}
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.
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 parametruout
w kodzie wywołującym, ale wartość zostanie utracona podczas wykonywania funkcji.
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.
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.
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)
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();
}
}
}
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 iout
Słowa kluczowe są używane do przekazywania -reference
.
Zmienna słowa kluczowego
ref
musi mieć wartość lub musi odnosić się do obiektu lubnull
przed jej przemijaniem.
W przeciwieństwie do
ref
, zmienna słowa kluczowegoout
musi mieć wartość lub musi odnoszą się do obiektu lubnull
po jego przemijaniu, jak również nie ma potrzeby aby mieć wartość lub odwoływać się do obiektu przed mijam.
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);
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.
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
lubout
jeśli wszystko co zamierzasz zrobić to zmodyfikować wewnątrz instancjiMyClass
przekazywanej w argumenciesomeClass
.- metoda wywołująca zobaczą zmiany takie jak
someClass.Message = "Hello World"
czy używaszref
,out
or nothing - zapis
someClass = new MyClass()
wewnątrzmyFunction(someClass)
zamienia obiekt widziany przezsomeClass
tylko w zakresie metodymyFunction
. Metoda wywołująca nadal wie o oryginalnej instancjiMyClass
, którą utworzyła i przekazała do Twojej metody
- metoda wywołująca zobaczą zmiany takie jak
-
You need
ref
lubout
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ątrzmyFunction(out someClass)
zmienia obiekt widziany metodą, która wywołałamyFunction
- pisanie
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]}
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 kopiaStringList
o nazwieLiStri
. 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] } kolejnyList<string>
obiekt wewnątrz metody, który nie wpływa oryginalna lista.HalloWelt
:LiStriRef
jest aliasem już zainicjowanegoListStringRef
. Przekazywany obiektList<string>
jest służy do inicjalizacji nowy, zatemref
był konieczny.CiaoMondo
:LiStriOut
jest aliasemListStringOut
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.
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ś.
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).
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; }
}
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
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.
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.
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.
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.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