Pregunta ¿Cuál es la diferencia entre las palabras clave 'ref' y 'out'?


Estoy creando una función donde necesito pasar un objeto para que pueda ser modificado por la función. Cuál es la diferencia entre:

public void myFunction(ref MyClass someClass)

y

public void myFunction(out MyClass someClass)

¿Qué debería usar y por qué?


718
2017-12-23 09:16


origen


Respuestas:


ref le dice al compilador que el objeto se inicializó antes de ingresar a la función, mientras out le dice al compilador que el objeto se inicializará dentro de la función.

Entonces, mientras ref es bidireccional, out está fuera-solo.


973
2017-12-23 09:18



los ref modificador significa que:

  1. El valor ya está establecido y
  2. El método puede leerlo y modificarlo.

los out modificador significa que:

  1. El valor no está establecido y no puede leerse con el método hasta esta organizado.
  2. El método debe establecerlo antes de regresar.

430
2017-12-23 12:40



Digamos que Dom aparece en el cubículo de Peter sobre la nota sobre los informes TPS.

Si Dom fuera un argumento de referencia, tendría una copia impresa de la nota.

Si Dom fuera un argumento, haría que Peter imprimiera una nueva copia del memorando para que se la llevara.


129
2018-03-23 19:33



Voy a probar mi mano en una explicación:

Creo que entendemos cómo funcionan los tipos de valores, ¿verdad? Los tipos de valor son (int, long, struct, etc.). Cuando los envía a una función sin un comando de referencia, COPIA el datos. Cualquier cosa que hagas con esos datos en la función solo afecta la copia, no el original. El comando ref envía datos REALES y cualquier cambio afectará los datos fuera de la función.

Ok sobre la parte confusa, tipos de referencia:

Permite crear un tipo de referencia:

List<string> someobject = new List<string>()

Cuando vuelves a subir algún objeto, se crean dos partes:

  1. El bloque de memoria que contiene datos para algún objeto.
  2. Una referencia (puntero) a ese bloque de datos.

Ahora cuando envías algún objeto en un método sin ref. COPIAS referencia puntero, NO los datos. Entonces ahora tienes esto:

(outside method) reference1 => someobject
(inside method)  reference2 => someobject

Dos referencias que apuntan al mismo objeto. Si modifica una propiedad en algún objeto utilizando reference2 afectará los mismos datos apuntados por reference1.

 (inside method)  reference2.Add("SomeString");
 (outside method) reference1[0] == "SomeString"   //this is true

Si anula la referencia2 o la señala a datos nuevos, no afectará a la referencia1 ni a la referencia de datos1.

(inside method) reference2 = new List<string>();
(outside method) reference1 != null; reference1[0] == "SomeString" //this is true

The references are now pointing like this:
reference2 => new List<string>()
reference1 => someobject

Ahora que pasa cuando envias algún objeto por ref a un método? los referencia real a algún objeto se envía al método. Entonces ahora solo tiene una referencia a los datos:

(outside method) reference1 => someobject;
(inside method)  reference1 => someobject;

Pero ¿qué significa esto? Actúa exactamente igual que el envío de un objeto no por ref a excepción de dos cosas principales:

1) Cuando anula la referencia dentro del método, anulará la que está fuera del método.

 (inside method)  reference1 = null;
 (outside method) reference1 == null;  //true

2) Ahora puede señalar la referencia a una ubicación de datos completamente diferente y la referencia fuera de la función ahora apuntará a la nueva ubicación de datos.

 (inside method)  reference1 = new List<string>();
 (outside method) reference1.Count == 0; //this is true

44
2017-09-23 17:55



ref está en y fuera.

Deberías usar out de preferencia donde sea suficiente para sus requerimientos.


26
2017-12-23 09:17



fuera:

En C #, un método puede devolver solo un valor. Si desea devolver más de un valor, puede usar la palabra clave out. El modificador de salida devuelve como retorno por referencia. La respuesta más simple es que la palabra clave "out" se usa para obtener el valor del método.

  1. No necesita inicializar el valor en la función de llamada.
  2. Debe asignar el valor en la función llamada, de lo contrario el compilador informará un error.

árbitro:

En C #, cuando pasa un tipo de valor como int, float, double, etc. como argumento para el parámetro de método, se pasa por valor. Por lo tanto, si modifica el valor del parámetro, no afecta el argumento en la llamada al método. Pero si marca el parámetro con la palabra clave "ref", se reflejará en la variable real.

  1. Debe inicializar la variable antes de llamar a la función.
  2. No es obligatorio asignar ningún valor al parámetro ref en el método. Si no cambia el valor, ¿cuál es la necesidad de marcarlo como "ref"?

12
2018-04-01 18:31



Extendiendo el perro, ejemplo de gato. El segundo método con ref cambia el objeto al que hace referencia la persona que llama. De ahí "Cat" !!!

    public static void Foo()
    {
        MyClass myObject = new MyClass();
        myObject.Name = "Dog";
        Bar(myObject);
        Console.WriteLine(myObject.Name); // Writes "Dog". 
        Bar(ref myObject);
        Console.WriteLine(myObject.Name); // Writes "Cat". 
    }

    public static void Bar(MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

    public static void Bar(ref MyClass someObject)
    {
        MyClass myTempObject = new MyClass();
        myTempObject.Name = "Cat";
        someObject = myTempObject;
    }

10
2018-05-19 13:35