2009-09-06 12 views
12

In C++, passando riferimenti const è una pratica comune - per esempio:Come faccio a passare un riferimento const in C#?

#include <iostream> 
using namespace std; 

class X 
{ 
    public : 
    X()        {m_x = 0; } 
    X(const int & x)     {m_x = x; } 
    X(const X & other)    { *this = other; } 
    X & operator = (const X & other) { m_x = other.m_x; return *this; } 
    void print()      { cout << m_x << endl; } 
    private : 
    int m_x; 
}; 

void main() 
{ 
    X x1(5); 
    X x2(4); 
    X x3(x2); 
    x2 = x1; 
    x1.print(); 
    x2.print(); 
    x3.print(); 
} 

Questo semplice esempio illustra come si fa - più o meno. Comunque ho notato che in C# questo non sembra essere il caso. Devo passare i riferimenti const in C#? per cosa ho bisogno della parola chiave "ref"? Si noti che conosco e capisco quali sono i riferimenti e i tipi di valore C#.

+1

Dal momento che si sta pensando in termini probabilmente C++ il modo migliore di pensare la parola chiave ref è come un puntatore. Se lo si utilizza con un tipo di valore, si tratta di un singolo puntatore, con un tipo di riferimento è un puntatore a un puntatore. –

+0

Duplicato: http://stackoverflow.com/questions/114149 –

+0

Un buon riferimento per questo genere di cose è il blog di Eric Lipperts. In particolare la sua voce "Riferimenti non è indirizzi". http://blogs.msdn.com/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx –

risposta

13

C# non ha il concetto di oggetti const (ossia oggetti che non è possibile modificare); solo le variabili (cioè i campi) possono essere const o readonly, ovvero non è possibile assegnarle.

La parola chiave ref passa concettualmente un riferimento a una variabile come parametro, ovvero il destinatario può modificare la variabile (anziché modificare semplicemente il valore). Questo è particolarmente utile per i tipi primitivi (int, bool, ecc.).

+2

In realtà, int non è immutabile in senso stretto, in quanto può essere modificato dopo la creazione (mentre l'oggetto immutabile non può essere modificato dopo che è stato creato). Il problema con int e altri tipi primitivi è che vengono passati per valore, quindi in realtà è possibile cambiarli in funzione, ma si modificheranno la loro copia, non se stessi. Quindi preferisco scrivere "tipi immutabili e tipi primitivi". –

+1

Ok, ho lasciato cadere la menzione di immutabile. –

+2

Come modificherebbe un int? L'assegnazione non conta (potresti anche 'modificare' tipi di riferimento immutabili assegnando un nuovo riferimento). int è sia un tipo di valore che immutabile.In effetti, per i tipi immutabili, non si può veramente capire la differenza tra i tipi di riferimento e di valore (eccetto usando ReferenceEquals). Solo se un tipo è mutabile (ha setter di proprietà o metodi mutanti), la differenza tra riferimento e valore inizia a giocare un ruolo. La maggior parte dei tipi di valore in .NET sono immutabili (tutti i tipi primitivi, DateTime, TimeSpan, ecc.) – Daniel

20

Per rispondere alla parte di riferimento della domanda; quando si passa una variabile a un metodo, viene creata una copia di tale variabile. Usando la parola chiave ref passerà la stessa istanza di quella variabile in modo che il metodo sia in grado di aggiornare quella variabile per il chiamante.

Un sacco di gente sembra pensare che questo si applica solo ai tipi di valore perché i tipi di riferimento sono appena passati come riferimento in ogni caso quindi la parola chiave ref non ha alcun effetto. Tuttavia, questo non è vero, il riferimento viene passato al metodo nello stesso modo di un valore; viene copiato e viene creata una nuova istanza del riferimento . Ciò significa che il chiamante vedrà le modifiche all'oggetto stesso, ma non al riferimento. Quindi, se si è tentato di impostare l'oggetto a null o un nuovo oggetto, il chiamante potrebbe non vedere questa modifica se la parola chiave ref non viene utilizzato:

Senza ref:

void UpdatePerson(Person person) 
{ 
    // Caller would see this change 
    person.Name = "Bob"; 
    // Caller wouldn't see this change 
    person = null; 
} 

con rif

void UpdatePerson(ref Person person) 
{ 
    // Caller would see this change 
    person.Name = "Bob"; 
    // Caller would see this change 
    person = null; 
} 
+0

Proveniente da C++, il primo esempio ** Without Ref ** è molto strano! Quindi l'oggetto 'Persona' passato come argomento viene copiato su un oggetto' Person' locale all'interno di 'UpdatePerson (Person) 'e le modifiche ai membri del campo dell'argomento sono consentite come se l'argomento fosse passato per riferimento, ma le modifiche all'oggetto locale non ha alcun effetto sull'argomento oggetto? –

Problemi correlati