2009-09-06 20 views
12

En C++, pasando referencias const es una práctica común - por ejemplo:¿Cómo paso una referencia constante en 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(); 
} 

Este sencillo ejemplo ilustra cómo se hace - más o menos. Sin embargo, he notado que en C# no parece ser el caso. ¿Debo pasar las referencias de const en C#? ¿Para qué necesito la palabra clave "ref"? Tenga en cuenta que sé y entiendo qué referencias de C# y tipos de valores son.

+1

Puesto que usted está pensando en términos de C++, probablemente, la mejor manera de pensar en la palabra clave ref es como un puntero. Si lo usa con un tipo de valor, entonces es un puntero único, con un tipo de referencia, es un puntero a un puntero. –

+0

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

+0

Una buena referencia para este tipo de cosas es el blog Eric Lipperts. En particular, su entrada "Referencias no son direcciones". http://blogs.msdn.com/ericlippert/archive/2009/02/17/references-are-not-addresses.aspx –

Respuesta

13

C# no tiene la noción de objetos const (es decir, objetos que no se pueden modificar); solo las variables (es decir, los campos) pueden ser const o readonly, lo que significa que no puede asignarlas.

La palabra clave ref pasa conceptualmente una referencia a una variable como parámetro, es decir, el destinatario puede modificar la variable (en lugar de simplemente modificar el valor). Esto es particularmente útil para los tipos primitivos (int, bool, etc.).

+2

En realidad, int no es inmutable en sentido estricto, ya que puede modificarse después de la creación (mientras que el objeto inmutable no se puede cambiar después de haber sido creado). El problema con int y otro tipo primitivo es que se pasan por valor, por lo que en realidad puede cambiarlos en función, pero alterará su copia, no ellos mismos. Así que preferiría escribir "tipos inmutables y tipos primitivos". –

+1

Ok, dejé de mencionar lo inmutable. –

+2

¿Cómo modificarías un int? La asignación no cuenta (también podría 'modificar' los tipos de referencia inmutables asignando una nueva referencia). int es a la vez un tipo de valor e inmutable.De hecho, para los tipos inmutables, no se puede distinguir la diferencia entre los tipos de referencia y de valor (excepto mediante el uso de ReferenceEquals). Solo si un tipo es mutable (tiene instaladores de propiedades o métodos de mutación), la diferencia entre referencia y valor comienza a desempeñar un papel. La mayoría de los tipos de valor en .NET son inmutables (todos los tipos primitivos, DateTime, TimeSpan, etc.) – Daniel

20

Para responder a la parte ref de su pregunta; cuando pasa una variable a un método, se crea una copia de esa variable. El uso de la palabra clave ref pasará la misma instancia de esa variable para que el método pueda actualizar esa variable para la persona que llama.

Mucha gente parece pensar que esto solo se aplica a los tipos de valores porque los tipos de referencia se pasan como referencia de todos modos, por lo que la palabra clave ref no tiene efecto. Sin embargo, esto no es cierto, la referencia se pasa al método de la misma manera que un valor; se copia y se crea una nueva instancia de esa referencia. Esto significa que la persona que llama verá modificaciones al objeto en sí, pero no a la referencia. Por lo tanto, si se trató de establecer el objeto a null, o un nuevo objeto, la persona que llama no vería esta modificación si la palabra clave ref no se utiliza:

Sin ref:

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

con referencia

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

Viniendo de C++, el primer ejemplo ** Sin Ref ** es muy extraño. Así que el objeto 'Persona' pasado como argumento se copia a un objeto local' Persona' dentro de 'UpdatePerson (Person)' y las modificaciones a los miembros del campo del argumento se permiten como si el argumento se pasara por referencia, pero las modificaciones al objeto local no afecta el argumento objeto en absoluto? –

Cuestiones relacionadas