Rozumiem, że jeśli mijam typu wartość ( int
, struct
, itd.) Jako parametr (bez ref
hasła), kopia tej zmiennej jest przekazywany do metody, ale jeśli mogę użyć ref
słowa kluczowego odniesienie do tej zmiennej jest przekazywana, nie nowy.
Ale w przypadku typów referencyjnych, takich jak klasy, nawet bez ref
słowa kluczowego, referencja jest przekazywana do metody, a nie kopia. Więc jakie jest zastosowanie ref
słowa kluczowego z typami referencyjnymi?
Weź na przykład:
var x = new Foo();
Jaka jest różnica między następującymi?
void Bar(Foo y) {
y.Name = "2";
}
i
void Bar(ref Foo y) {
y.Name = "2";
}
c#
parameters
pass-by-reference
pass-by-value
Andreas Grech
źródło
źródło
Istnieją przypadki, w których chcesz zmodyfikować rzeczywiste odniesienie, a nie wskazany obiekt:
źródło
Jon Skeet napisał świetny artykuł o przekazywaniu parametrów w C #. Wyszczególnia dokładnie dokładne zachowanie i użycie przekazywania parametrów przez wartość, przez odwołanie (
ref
) i przez wyjście (out
).Oto ważny cytat z tej strony w odniesieniu do
ref
parametrów:źródło
Bardzo ładnie wyjaśniono tutaj: http://msdn.microsoft.com/en-us/library/s6938f28.aspx
Streszczenie z artykułu:
źródło
Gdy przekazujesz typ odwołania za pomocą słowa kluczowego ref, przekazujesz odwołanie przez odwołanie, a wywoływana metoda może przypisać nową wartość do parametru. Ta zmiana zostanie przeniesiona na zakres wywołujący. Bez ref odwołanie jest przekazywane przez wartość i tak się nie dzieje.
C # ma również słowo kluczowe „out”, które jest bardzo podobne do ref, z tą różnicą, że w przypadku „ref” argumenty muszą zostać zainicjowane przed wywołaniem metody, a bez „out” należy przypisać wartość w metodzie odbierającej.
źródło
Pozwala na modyfikację przekazanej referencji. Np
Możesz również użyć , jeśli nie obchodzi Cię przekazana referencja:
źródło
Kolejny kod
źródło
Oprócz istniejących odpowiedzi:
Jak prosiłeś o różnicę między dwiema metodami: Nie ma co (ntra) wariancji podczas używania
ref
lubout
:źródło
Parametr w metodzie wydaje się zawsze przekazywać kopię, pytanie jest kopią czego. Kopia jest wykonywana przez konstruktor kopiujący dla obiektu, a ponieważ wszystkie zmienne są Object w C #, wierzę, że tak jest w przypadku wszystkich z nich. Zmienne (obiekty) są jak ludzie mieszkający pod niektórymi adresami. Albo zmieniamy osoby mieszkające pod tymi adresami, albo możemy utworzyć więcej odniesień do osób mieszkających pod tymi adresami w książce telefonicznej (rób płytkie kopie). Tak więc więcej niż jeden identyfikator może odnosić się do tego samego adresu. Typy referencyjne wymagają więcej miejsca, więc w przeciwieństwie do typów wartości, które są bezpośrednio połączone strzałką z ich identyfikatorem w stosie, mają wartość dla innego adresu w stercie (większa przestrzeń do zamieszkania). To miejsce należy zabrać ze stosu.
Typ wartości: Indentifier (zawiera wartość = adres wartości stosu) ----> Wartość typu wartości
Typ odniesienia: Identyfikator (zawiera wartość = adres wartości stosu) ----> (zawiera wartość = adres wartości sterty) ----> Wartość sterty (najczęściej zawiera adresy do innych wartości), wyobraź sobie więcej strzałek wbijających się w różne kierunki do Array [0], Array [1], array [2]
Jedynym sposobem zmiany wartości jest podążanie za strzałkami. Jeśli jedna strzałka zostanie zgubiona / zmieniona w sposób, w jaki wartość jest nieosiągalna.
źródło
Zmienne referencyjne przenoszą adres z jednego miejsca do drugiego, więc każda aktualizacja ich w dowolnym miejscu będzie odzwierciedlać wszystkie miejsca, WTEDY, jakie jest zastosowanie REF. Zmienna referencyjna (405) jest dobra, dopóki żadna nowa pamięć nie zostanie przydzielona zmiennej referencyjnej przekazanej w metodzie.
Po przydzieleniu nowej pamięci (410) zmiana wartości tego obiektu (408) nie będzie wszędzie widoczna. Przychodzi ten ref. Ref jest odniesieniem do odniesienia, więc za każdym razem, gdy alokuje nową pamięć, należy ją poznać, ponieważ wskazuje na tę lokalizację, dlatego wartość może być współdzielona przez everyOne. Możesz zobaczyć obraz dla większej przejrzystości.
źródło