Qual è l'uso di “ref” per le variabili di riferimento di tipo in C #?
-
12-09-2019 - |
Domanda
Ho capito che se mi passa un valore di tipo (int
, struct
, etc.) come parametro (senza la parola chiave ref
), una copia di tale variabile viene passata al metodo, ma se uso la parola ref
un viene passato riferimento a quella variabile, non è uno nuovo.
Ma con riferimento-tipi, come le classi, anche senza la parola chiave ref
, viene passato un riferimento al metodo, non una copia. Allora, qual è l'uso della parola chiave ref
con riferimento tipi?
Prendiamo ad esempio:
var x = new Foo();
Qual è la differenza tra i seguenti?
void Bar(Foo y) {
y.Name = "2";
}
e
void Bar(ref Foo y) {
y.Name = "2";
}
Soluzione
È possibile modificare ciò foo
punti da utilizzare y
:
Foo foo = new Foo("1");
void Bar(ref Foo y)
{
y = new Foo("2");
}
Bar(ref foo);
// foo.Name == "2"
Altri suggerimenti
Ci sono casi in cui si desidera modificare l'attuale di riferimento e non l'oggetto puntato:
void Swap<T>(ref T x, ref T y) {
T t = x;
x = y;
y = t;
}
var test = new[] { "0", "1" };
Swap(ref test[0], ref test[1]);
un grande articolo su parametro che passa in C #. Dettaglia chiaramente il comportamento e l'utilizzo di passaggio di parametri per valore, per riferimento (ref
) esatto, e dall'uscita (out
).
Ecco un preventivo importante da quella pagina in relazione ai parametri ref
:
Parametri di riferimento non passano il valori delle variabili utilizzate nella membro invocazione funzione - usano le variabili stesse. Piuttosto che creazione di un nuovo percorso di archiviazione per la variabile nel membro funzione dichiarazione, la stessa posizione di memorizzazione viene utilizzato, in modo che il valore della variabile nel membro funzione e il valore del parametro di riferimento sarà sempre essere lo stesso. Parametri di riferimento hanno bisogno l'arbitro modificatore come parte sia dichiarazione e l'invocazione - che significa che è sempre chiaro quando sei passando qualcosa per riferimento.
Molto ben spiegato qui: http://msdn.microsoft.com/en-us/library/s6938f28.aspx
Estratto dall'articolo:
Una variabile di un tipo di riferimento non contiene direttamente i suoi dati; esso contiene un riferimento ai suoi dati. Quando si passa un riferimento di tipo parametro per valore, è possibile modificare i dati a cui punta il riferimento, ad esempio il valore di un membro della classe. Tuttavia, è non può modificare il valore del riferimento stesso; che è, non si può utilizzare lo stesso riferimento allocare memoria per una nuova classe e falla persistere all'esterno del blocco. Per fare questo, passare il parametro utilizzando il ref o parola chiave fuori.
Quando si passa un tipo di riferimento con la parola chiave ref, si passa il riferimento per riferimento, e il metodo si chiama possibile assegnare un nuovo valore al parametro. Questo cambiamento si propaga al campo di applicazione chiamando. Senza ref, il riferimento è passato per valore, e questo non accade.
C # ha anche la parola 'out', che è un po 'come ref, se non che con 'ref', gli argomenti devono essere inizializzati prima di chiamare il metodo, e con la 'fuori' è necessario assegnare un valore nel metodo di ricezione.
Permette di modificare il riferimento passato in. Es.
void Bar()
{
var y = new Foo();
Baz(ref y);
}
void Baz(ref Foo y)
{
y.Name = "2";
// Overwrite the reference
y = new Foo();
}
È inoltre possibile utilizzare se non si preoccupano il riferimento passato in:
void Bar()
{
var y = new Foo();
Baz(out y);
}
void Baz(out Foo y)
{
// Return a new reference
y = new Foo();
}
Un altro mucchio di codice
class O
{
public int prop = 0;
}
class Program
{
static void Main(string[] args)
{
O o1 = new O();
o1.prop = 1;
O o2 = new O();
o2.prop = 2;
o1modifier(o1);
o2modifier(ref o2);
Console.WriteLine("1 : " + o1.prop.ToString());
Console.WriteLine("2 : " + o2.prop.ToString());
Console.ReadLine();
}
static void o1modifier(O o)
{
o = new O();
o.prop = 3;
}
static void o2modifier(ref O o)
{
o = new O();
o.prop = 4;
}
}
In aggiunta alle risposte esistenti:
Per quanto hai chiesto per la differenza dei 2 metodi: Non c'è co (Ntra) varianza quando si utilizza ref
o out
:
class Foo { }
class FooBar : Foo { }
static void Bar(Foo foo) { }
static void Bar(ref Foo foo) { foo = new Foo(); }
void Main()
{
Foo foo = null;
Bar(foo); // OK
Bar(ref foo); // OK
FooBar fooBar = null;
Bar(fooBar); // OK (covariance)
Bar(ref fooBar); // compile time error
}
Un parametro in un metodo sembra essere sempre passare una copia, la domanda è una copia di quello. Una copia è fatto da un costruttore di copia per un oggetto e dal momento che tutte le variabili sono oggetto in C #, credo che questo sia il caso per tutti loro. Variabili (oggetti) sono come le persone che vivono in alcuni indirizzi. O ci cambiamo le persone che vivono in quegli indirizzi o possiamo creare più riferimenti alle persone che vivono in quegli indirizzi in rubrica (fare copie poco profonde). Così, più di un identificatore può fare riferimento allo stesso indirizzo. I tipi di riferimento desiderare di più spazio, quindi a differenza di tipi di valore che sono direttamente collegati da una freccia alla loro identificazione nella pila, che hanno valore per un altro indirizzo nel mucchio (uno spazio più grande di abitare). Questo spazio deve essere presa dal mucchio.
Tipo di valore: Identificatore (contiene value = indirizzo del valore di pila) ----> Valore del tipo di valore
Tipo di riferimento: Identifier (contiene value = indirizzo del valore pila) ----> (contiene value = indirizzo del valore mucchio) ----> valore Heap (più spesso contiene indirizzi ad altri valori), immaginate più frecce attaccare in diverse direzioni per Array [0], Array [1], matrice [2]
L'unico modo per modificare un valore deve seguire le frecce. Se una freccia si perde / modificato nel modo in cui il valore non è raggiungibile.
variabili di riferimento portano l'indirizzo da un luogo all'altro in modo che qualsiasi updation su di loro in qualsiasi luogo rifletterà su tutti i luoghi allora che cosa è l'uso di REF. variabile di riferimento (405) sono buoni finché non nuova memoria viene allocata alla variabile di riferimento passata nel metodo.
Una volta che la nuova memoria allocare (410) allora la variazione del valore su questo oggetto (408) non rifletterà in tutto il mondo. Per questo riferimento viene. Ref è riferimento di riferimento così ogni volta nuova memoria allocare che arrivare a conoscere perché punta a quella posizione quindi il valore può essere condiviso da tutti. Potete vedere l'immagine per più clearity.