Pregunta

Saludos,

Tengo la diferencia entre el paso por valor y pasar por referencia. Pero la referencia pase (como matriz) por ref y pasar matriz por valor es algo que parece que no puede comprender. ¿Cómo se puede pasar una referencia por referencia?

     int[] myArray = {1,2,3};
     PassByVal(myArray);
     PassByRef(ref myArray);

     PassByVal(int[] array)
     {    array = new int[] {7,8,9};   // will not work }

     PassByRef(ref int[] array)
     {    array = new int[] {10,11,12}; }  // will work
¿Fue útil?

Solución

Le sugiero que consulte este enlace . Es bastante útil y contiene ejemplos muy simples sobre paso de parámetros en C # .

Parámetros de referencia no pasan los valores de las variables utilizadas en el miembro de la función de invocación - que utilizan las variables mismas. lugar de crear una nueva ubicación de almacenamiento para la variable en la declaración miembro de función, se utiliza la misma ubicación de almacenamiento , por lo que el valor de la variable en el elemento de función y el valor del parámetro de referencia siempre será lo mismo. parámetros de referencia tienen el modificador ref tanto como parte de la declaración y la invocación - Eso significa que siempre está claro cuando estás pasando algo por referencia. Echemos un vistazo a los ejemplos anteriores, sólo cambiando el parámetro a ser un parámetro de referencia:

void Foo (ref StringBuilder x) {
    x = null;
}

...

StringBuilder y = new StringBuilder();
y.Append ("hello");
Foo (ref y);
Console.WriteLine (y==null); // will write TRUE

en su ejemplo

int[] myArray = {1,2,3};
PassByVal(myArray);
PassByRef(ref myArray);

PassByVal(int[] array){
    // the function copy the value of the pointer in a new location of memory
    // the "copied" pointer stil poin to the array 123    

    // now you are modifying the object pointed by THE COPY of the pointer
    // the original pointer stil point to array 123
    // the copoy of the pointer will point to array 456
    array = new int[] {7,8,9}; 

} // will not work

PassByRef(ref int[] array){
   // here you are passing the pointer without creating a copy of it in a 
   // new location of memory

   // we have not a original pointer and a "copyed" pointer
   // we have only the original pointer and now whe point it to array 10,11,12
   array = new int[] {10,11,12}; 
}  // will work

Otros consejos

Si se pasa una referencia por referencia que puede hacer que la variable pasada en el punto a un nuevo objeto. Si pasa la referencia por el valor todavía se puede cambiar el estado del objeto, pero no se puede hacer el punto variable a un objeto diferente.

Ejemplo:

void RefByRef(ref object x)
{
  x=new object(2);
}

void RefByValue(object x)
{
 x=new object(2);//Only changes a local variable and gets discarded once the function exits
}

void Test()
{
  object x1=1;
  object x1a=x1;
  RefByRef(ref x1);
  //x1 is now a boxed 2
  //x1a is still a boxed 1


  object x2=1;
  RefByValue(x2);
  //x2 is still a boxed 1
}

Con el fin de responder a la primera mirada a su pregunta nos dejó en valuetypes Un ValueType mantiene el valor. Es decir no lo hace, a su vez punto a otro de la memoria que contiene el valor, sino más bien para la ubicación de la memoria es el valor.

por lo int i = 10;

int j = i;

Lo que sucede aquí es que una copia del valor de i se asigna a j. Ambos tienen el mismo valor, pero son diferentes ubicaciones en la memoria. En palabras oter, cada vez que se asigne un valuetype a otro valuetype, se hace una copia.

Contrato esto con ReferenceTypes.

objeto o = 10;

objeto p = O;

porque o es un ReferenceType o apunta a una ubicación de memoria que contiene el valor de 10 (en realidad está en caja, pero voy a mantenerlo simple). En la siguiente línea p ahora apunta a la misma posición de memoria. En otras palabras, tyes de referencia tienen dos cosas que suceden. 1. Un puntero de dirección 2. La ubicación de memoria real (que dirección apunta a) que mantiene la "cosa" real.

Si lo consigue hacer mucho, entonces puede moverse sobre el paso por valor y por referencia.

En C # parámetros se pasan por valor. Así que si estás pasando un valueType a un método que espera un parámetro valuetype, entonces

int i = 10;
SomeMethod(i);
Console.WriteLine(i);

static void SomeMethod(int value)
{
  value = 20;
}

Cuando se hace la llamada a SomeMethod una copia del valor de i se envía al método. Si el método manipula el parámetro, que no afecta a la variable original i. Así que lo que verá en la ventana de la consola es 10;

contraiga esto con los tipos de referencia;

  class Program
  {
    static void Main(string[] args)
    {
      Customer c = new Customer() { Name = "Mike" };
      SomeMethod(c);
      Console.WriteLine(c.Name);
    }

    static void SomeMethod(Customer customer)
    {
      customer.Name = "John";
    }
  }

  class Customer
  {
    public string Name { get; set; }
  }

Desde c es un tipo de referencia. Y C # pasa los parámetros por valor. se pasa una copia del "valor" de la referencia. Ese es el valor de la Dirección c está señalando es pasado. En el procedimiento, ya que la dirección es la misma (que es una copia, sino que apunta a la misma posición de memoria), el método es capaz de manipular el estado del objeto. Así que lo que verá en la ventana de la consola es "Juan" y no "Mike".

Sin embargo, si los intentos método para asignar otra instancia al parámetro (llamado "cliente" en este caso). entonces el cambio cosas.

  class Program
  {
    static void Main(string[] args)
    {
      Customer c = new Customer() { Name = "Mike" };
      SomeMethod(c);
      Console.WriteLine(c.Name);
    }

    static void SomeMethod(Customer customer)
    {
      customer = new Customer();
      customer.Name = "John";
    }
  }

  class Customer
  {
    public string Name { get; set; }
  }

Tenga en cuenta que en el método se crea una nueva instancia de un cliente y lo asignamos al cliente de parámetros y fijamos el nombre de esta nueva instancia de "John". Lo que vamos a ver en la ventana de la consola es "Mike" y no Juan.

Eso es debido a que una copia de la variable original (c) se hizo antes de pasarlo al método. Aunque ahora en el método que tenemos otra dirección y luego manipular ese nueva dirección para la instancia original está intacta. Tiene sentido?

Está bien, si eso tiene sentido. a continuación, ¿qué pasaría si en realidad quería la SomeMethod a ser capaz de hacer lo que hemos tratado de hacer? Bueno, entonces el parámetro no puede ser pasado por valor, pero tiene que ser pasado por referencia. Lo que significa que la variable c, y los dos parte (el valor de dirección que está apuntando y la dirección de sí mismo) se están pasando. Así que ahora estás pasando un tipo de referencia por referencia.

  class Program
  {
    static void Main(string[] args)
    {
      Customer c = new Customer() { Name = "Mike" };
      SomeMethod(ref c);
      Console.WriteLine(c.Name);
    }

    static void SomeMethod(ref Customer customer)
    {
      customer = new Customer();
      customer.Name = "John";
    }
  }

  class Customer
  {
    public string Name { get; set; }
  }

Esto puede parecer un poco confuso, pero no es realmente tan difícil. Cuando se asigna una instancia de un tipo de referencia a una variable, se podría decir que el valor de esa variable será referencia para el objeto, no el objeto en sí. Cuando se pasa esa variable por valor a otro método, que está pasando una copia de la referencia. El método llamado "verá" la misma instancia que el código de llamada hace. Si por el contrario pasa la variable por referencia, el método de llamada llega a ver el misma copia de la referencia como el código de llamada hace.

La diferencia de comportamiento entre estos a es que cuando se pasa la variable por referencia, el método llamado podría asignar otro referencia a la variable (hacen referencia a otra instancia del mismo tipo), y el código llamando verá este cambio. A menos que usted hace de este destino, no hay necesidad de usar ref.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top