2012-03-15 14 views
14

Sé que el valor predeterminado es ByVal en C#. Usé los mismos nombres de variable en muchos lugares y luego noté que los valores pasados ​​cambian y vuelven. Creo que sabía que el mecanismo de alcance de C# era incorrecto. Aquí, la licencia pública prevalece sobre la licencia local de valores. Sé que puedo cambiar fácilmente el nombre de los nombres de las variables en conflicto, pero me gustaría aprender los hechos sobre el alcance.C# Al pasar los argumentos por defecto es ByRef en lugar de ByVal

public static class LicenseWorks 
    { 
    public static void InsertLicense(License license) 
    { 
     license.registered = true; 
     UpdateLicense(license); 
    } 
    } 

    public partial class formMain : Form 
    { 
    License license; 

    private void btnPay_Click(object sender, EventArgs e) 
    { 
      license.registered = false; 
      LicenseWorks.InsertLicense(license); 

      bool registered = license.registered; //Returns true! 
     } 
    }  

Actualización: he añadido a continuación como solución:

public static void InsertLicense(License license) 
    { 

     license = license.Clone(); 
     ... 
    } 

Respuesta

51

El argumento se pasa por valor - pero el argumento no es un objeto, es una referencia. Esa referencia se está pasando por valor, pero cualquier cambio realizado en el objeto a través de esa referencia seguirá siendo visto por la persona que llama.

Esto es muy diferente a paso real por referencia, donde los cambios a propio parámetro como este:

public static void InsertLicense(ref License license) 
{ 
    // Change to the parameter itself, not the object it refers to! 
    license = null; 
} 

Ahora bien, si se llama a InsertLicense(ref foo), se harán foo nula después. Sin la referencia, no lo haría.

Para obtener más información, ver a dos artículos que he escrito:

+0

OK consiguió pensé que haya sido duplicada. –

3

lo necesario para aprender la diferencia entre tipos de referencia y tipos de valor. Supongo que está utilizando una licencia de tipo de referencia, lo que significa que está analizando una referencia en la instancia en cuestión.

Ver: http://msdn.microsoft.com/en-us/library/aa711899(v=vs.71).aspx

Aunque, no necesariamente corregir un tipo de valor es a menudo asignado en la pila o dentro de un tipo de referencia. Mientras que los tipos de referencia siempre se asignan en el montón administrado.

+0

¡Ja! Por supuesto, Jon Skeet me ganó al golpe. – nietras

+0

No llame a las referencias "punteros". ¡Son animales completamente diferentes! –

+0

Lo sé, pero para poder explicar el punto aquí, pensé que era más claro, y esa también es la razón por la que lo puse entre comillas. – nietras

1

Al pasar una licencia en InsertLicense, no la pasa por valor sino como referencia. Eso significa que al cambiar el elemento registrado a verdadero, cambiará eso y después de devolver la referencia, el elemento registrado será verdadero.

1

Está pasando el argumento de licencia por valor; esencialmente, esto significa que puede modificar cualquier propiedad pública del objeto. Sin embargo, si se reasigna la referencia del objeto de la licencia a un nuevo objeto, es decir, si se hizo esto:

public static void InsertLicense(License license)  
{   
    license = new Licence();   
    UpdateLicense(license);  
} 

la persona que llama no se haga referencia al nuevo objeto de licencia se define en el método estático a menos que se pasó por ref .

Recuerde que todos los parámetros se pasan a los métodos por valor a menos que use las palabras clave ref o out.

0

corrió a través de esto y pensé que debería compartir lo que Microsoft dice:.

"No se debe confundir el concepto de paso por referencia con el concepto de los tipos de referencia Los dos conceptos no son los mismos un parámetro de método puede ser. modificado por ref independientemente de si es un tipo de valor o un tipo de referencia. No hay boxeo de un tipo de valor cuando se pasa por referencia ".

MSDN: ref (C# Reference)

Cuestiones relacionadas