Suscribirse al Feed
22Jul

Paso de variables Por Referencia vs Por Valor [C#]

En C#, como en Java, u otros lenguajes de programación, es posible pasar variables a los métodos (funciones) de dos maneras: Por referencia y Por valor. La diferencia entre el uno y el otro es básicamente que:

  • Cuando una variable es pasada por valor, el método recibe una copia del valor de la variable. Por lo tanto, los cambios realizados a esa variable dentro del contexto de la función, NO afecta a la variable original. Pero…
  • Cuando es pasada por referencia, el método recibe la referencia a la variable original. Por tanto los cambios realizados a esa variable dentro del contexto de la función, AFECTA a la variable original.

¿Cual debo usar?

Eso depende de lo que quieras hacer. Cada una tiene sus ventajas y desventajas. Al pasar una variable por valor, estás asegurando que dicho valor no va a ser modificado por equivocación. Por otro lado, al pasar una variable por referencia, aunque la variable puede ser modificada por equivocación, ahorramos tiempo de ejecución y memoria, puesto que no es necesario crear una copia de la variable.

Pasar variables por referencia

Todas las variables que pasamos a un método declarado normalmente, son por valor. Para pasar argumentos por referencia es necesario utilizar las palabras reservada ref o out, tanto al declarar el método como al invocarlo. Cuando pasamos un argumento usando ref, es necesario que dicha variable esté ya inicializada, de lo contrario obtendremos una excepción. Si la variable que deseamos pasar por referencia no está inicializada, es nesesario usar out, de tal manera que podamos inicializar la variable dentro del contexto del método.

Ejemplo…

En el siguiente ejemplo tenemos dos variables (y Y z), las cuales son procesadas por métodos que reciben variables por valor y por referencia. El resultado y el código son:


// Demostración de paso por valor y referencia
using System;
using System.Drawing;
using System.Windows.Forms;
namespace ValorReferencia
{
   public class ValorReferencia : Form
   {
      private Button mostrarSalida;
      private Label etiquetaResultado;
      public ValorReferencia()
      {
         this.mostrarSalida = new Button();
         this.etiquetaResultado = new Label();
         this.SuspendLayout();
         //Boton
         this.mostrarSalida.Location = new Point(105, 8);
         this.mostrarSalida.Name = "mostrarSalida";
         this.mostrarSalida.Size = new Size(130, 23);
         this.mostrarSalida.TabIndex = 0;
         this.mostrarSalida.Text = "Mostrar salida";
         this.mostrarSalida.Click += new System.EventHandler(this.mostrarSalida_Click);
         //Label
         this.etiquetaResultado.Location = new Point(10, 40);
         this.etiquetaResultado.Name = "etiquetaResultado";
         this.etiquetaResultado.Size = new Size(272, 104);
         this.etiquetaResultado.TabIndex = 1;
         this.AutoScaleBaseSize = new Size(5, 13);
         this.ClientSize = new Size(292, 175);
         this.Controls.AddRange(new Control[] {
            this.etiquetaResultado,
            this.mostrarSalida});
         this.Name = "Formulario";
         this.Text = "Valor vs Referencia";
         this.ResumeLayout(false);
      }
      static void Main()
      {
         Application.Run(new ValorReferencia());
      }
      // x es pasado por referencia y el metodo modifica
      // el valor original de la variable
      void CuadradoRef( ref int x )
      {
         x = x * x;
      }
      // x es pasado con el parametro out que inicializa y
      // modifica el valor original de la variable
      void CuadradoOut( out int x )
      {
         x = 6;
         x = x * x;
      }
      // x pasado por valor y el metodo NO modifica
      // el valor original de la variable
      void Cuadrado( int x )
      {
         x = x * x;
      }
      private void mostrarSalida_Click(
         object sender, System.EventArgs e )
      {
         int y = 5; // crear nuevo entero e inicializarlo a 5
         int z;     // declarar z, pero no incializarlo
         // mostrar valores originales de 'y' y 'z'
         etiquetaResultado.Text = "Valor original de y: " + y + "\n";
         etiquetaResultado.Text += "Valor original de z: uninitialized\n\n";
         // pasar 'y' y 'z' por referencia
         CuadradoRef( ref y );
         CuadradoOut( out z );
         // mostrar valores de 'y' y 'z' despues
        // de ser modificados por CuadradoRef y CuadradoOut
         etiquetaResultado.Text += "Valor de y despues de CuadradoRef: " + y + &uot;\n";
         etiquetaResultado.Text += "Valor de z despues de CuadradoOut: " + z + "\n\";
         // pasar y y z por valor
         Cuadrado( y );
         Cuadrado( z );
         // mostrar que los valores no han cambiado
         etiquetaResultado.Text += "Valor de y despues de Cuadrado: " + y + &uot;\n";
         etiquetaResultado.Text += "Valor de z despues de Cuadrado: " + z + "\n";
      } // end method mostrarSalida_Click
   }
}

Descargar

Etiquetas: , ,
Los ejercicios utilizados en este post están basados en ejemplos del libro C# How to Program de Deitel. Se pone a disposición la descargar del programa original, desarrollado para trabajar sobre Visual Studio de Microsoft en plataformas Windows, y se encuentra en inglés. La versión simplificada está basada en la original, pero sin código basura insertado por Visual Studio, se encuentra en español y ha sido probada sobre Gnu/Linux usando Mono.
Esta entrada fue publicada el Julio 22, 2008 at 2:40 pm clasificada con las etiquetas .net, C-Sharp, mono, programación. Sigue cualquier comentario mediante RSS feed para este post. Puedes dejar un comentario con el formulario de abajo, o enviar un trackback en esta URL.

No hay comentarios

 

 

Antes de comentar... recuerda que no hago tareas

Te invito a subscribirte al feed RSS. ¿No sabes que es un lector de Feeds?

© 2007 - 2008 Dezinerfolio. Todos los derechos reservados.
Powered by Wordpress. Entradas RSS