Diferencia entre los parámetros de ref y out en .NET

¿Cuál es la diferencia entre out parámetros ref y out en .NET? ¿Cuáles son las situaciones donde uno puede ser más útil que el otro? ¿Qué sería un fragmento de código donde uno puede ser usado y otro no?

Son prácticamente iguales: la única diferencia es que una variable que pase como un parámetro de out no necesita inicializarse, pero pasarla como un parámetro de ref tiene que establecerse en algo.

 int x; Foo(out x); // OK int y; Foo(ref y); // Error: y should be initialized before calling the method 

Ref parámetros de Ref son para datos que pueden modificarse, out parámetros de out son para datos que son un resultado adicional para la función (por ejemplo, int.TryParse ) que ya están usando el valor de retorno para algo.

¿Por qué C # tiene tanto ‘ref’ como ‘out’?

El llamante de un método que toma un parámetro de salida no es necesario para asignar a la variable pasada como el parámetro de salida antes de la llamada; sin embargo, se requiere que el destinatario se asigne al parámetro out antes de regresar.

Por el contrario, los parámetros de referencia se consideran inicialmente asignados por la persona que llama. Como tal, no es necesario que el destinatario se asigne al parámetro ref antes de su uso. Los parámetros de referencia se pasan tanto dentro como fuera de un método.

Por lo tanto, out significa salir, mientras que ref es para entrar y salir.

Estos corresponden estrechamente a los parámetros [out] y [in,out] de las interfaces COM, las ventajas de out parámetros out son que las personas que llaman no necesitan pasar un objeto preasignado en los casos en que no es necesario por el método que se llama; esto evita tanto el costo de la asignación como cualquier costo que pueda asociarse con la clasificación (más probablemente con COM, pero no poco común en .NET).

ref y out permiten que el método llamado modifique un parámetro. La diferencia entre ellos es lo que sucede antes de realizar la llamada.

  • ref significa que el parámetro tiene un valor antes de entrar en la función. La función llamada puede leer y cambiar el valor en cualquier momento. El parámetro entra, luego sale

  • out significa que el parámetro no tiene ningún valor oficial antes de entrar en la función. La función llamada debe inicializarlo. El parámetro solo se apaga

Esta es mi forma favorita de verlo: ref es pasar variables por referencia. out es declarar un valor de retorno secundario para la función. Es como si pudieras escribir esto:

 // This is not C# public (bool, string) GetWebThing(string name, ref Buffer paramBuffer); // This is C# public bool GetWebThing(string name, ref Buffer paramBuffer, out string actualUrl); 

Aquí hay una lista más detallada de los efectos de cada alternativa:

Antes de llamar al método:

ref : la persona que llama debe establecer el valor del parámetro antes de pasarlo al método llamado.

out : El método de la persona que llama no es necesario para establecer el valor del argumento antes de llamar al método. Lo más probable es que no deberías. De hecho, cualquier valor actual se descarta.

Durante la llamada:

ref : El método llamado puede leer el argumento en cualquier momento.

out : el método llamado debe inicializar el parámetro antes de leerlo.

Llamadas remotas:

ref : El valor actual se calcula a la llamada remota. Costo de rendimiento adicional.

out : no se pasa nada a la llamada remota. Más rápido.

Técnicamente hablando, puedes usar siempre ref en lugar de out , pero out te permite ser más preciso sobre el significado del argumento y, a veces, puede ser mucho más eficiente.

Ejemplo para OUT: la variable obtiene el valor inicializado después de entrar en el método. Más tarde, se devuelve el mismo valor al método principal.

 namespace outreftry { class outref { static void Main(string[] args) { yyy a = new yyy(); ; // u can try giving int i=100 but is useless as that value is not passed into // the method. Only variable goes into the method and gets changed its // value and comes out. int i; a.abc(out i); System.Console.WriteLine(i); } } class yyy { public void abc(out int i) { i = 10; } } } 

Salida:

10

============================================

Ejemplo para Ref: La variable debe inicializarse antes de entrar en el método. Más tarde, el mismo valor o valor modificado se devolverá al método principal.

 namespace outreftry { class outref { static void Main(string[] args) { yyy a = new yyy(); ; int i = 0; a.abc(ref i); System.Console.WriteLine(i); } } class yyy { public void abc(ref int i) { System.Console.WriteLine(i); i = 10; } } } 

Salida:

  0 10 

==============================

Espero que esté claro ahora.

  • Una variable de ref debe inicializarse antes de pasarla.
  • Se debe establecer out variable de out en la implementación de su función
  • out parámetros de out se pueden considerar como variables de retorno adicionales (no de entrada)
  • ref parámetros ref se pueden considerar como variables de entrada y salida.

Parámetros de Ref y Out:

Los parámetros out y ref se utilizan para devolver valores en la misma variable, que pasa como argumento de un método. Estos dos parámetros son muy útiles cuando su método necesita devolver más de un valor.

Debe asignarle valor al parámetro out en el cuerpo del método de calee, de lo contrario, el método no se comstackrá.


Parámetro Ref: debe inicializarse antes de pasar al Método. La palabra clave ref en un parámetro de método hace que un método haga referencia a la misma variable que se pasó como un parámetro de entrada para el mismo método. Si realiza algún cambio en la variable, se reflejarán en la variable.

 int sampleData = 0; sampleMethod(ref sampleData); 

Ex del parámetro Ref

 public static void Main() { int i = 3; // Variable need to be initialized sampleMethod(ref i ); } public static void sampleMethod(ref int sampleData) { sampleData++; } 

Parámetro de salida: no es necesario inicializar antes de pasar al método. El parámetro out se puede usar para devolver los valores en la misma variable pasada como un parámetro del método. Cualquier cambio realizado en el parámetro se reflejará en la variable.

  int sampleData; sampleMethod(out sampleData); 

Ex de parámetro de salida

 public static void Main() { int i, j; // Variable need not be initialized sampleMethod(out i, out j); } public static int sampleMethod(out int sampleData1, out int sampleData2) { sampleData1 = 10; sampleData2 = 20; return 0; } 

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 regresa como retorno por referencia. La respuesta más simple es que la palabra clave “out” se usa para obtener el valor del método.

  • No necesita inicializar el valor en la función de llamada.
  • Debe asignar el valor en la función llamada, de lo contrario el comstackdor 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.

  • Debe inicializar la variable antes de llamar a la función.
  • 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”?

No es necesario configurar los parámetros de Ref en la función, mientras que los parámetros de salida se deben vincular a un valor antes de salir de la función. Las variables pasadas como salidas también pueden pasar a una función sin inicializarse.

out especifica que el parámetro es un parámetro de salida, es decir, no tiene ningún valor hasta que el método lo establece explícitamente.

ref especifica que el valor es una referencia que tiene un valor y cuyo valor puede cambiar dentro del método.

out parámetros de out se inicializan mediante el método llamado, los parámetros ref se inicializan antes de llamar al método. Por lo tanto, out parámetros de out se usan cuando solo se necesita obtener un valor de retorno secundario, los parámetros de ref se usan para obtener un valor y potencialmente devolver un cambio a ese valor (de forma secundaria al valor de retorno principal).

La palabra clave ref se usa para pasar valores por referencia. (Esto no impide que los valores pasados ​​sean tipos de valor o tipos de referencia). Los parámetros de salida especificados con la palabra clave out son para devolver valores desde un método.

Una diferencia clave en el código es que debe establecer el valor de un parámetro de salida dentro del método. Este no es el caso para los parámetros de ref.

Para obtener más detalles, consulte http://www.blackwasp.co.uk/CSharpMethodParameters.aspx

Un parámetro out es un parámetro ref con un atributo especial Out() agregado. Si un parámetro de un método C # se declara como out , el comstackdor requerirá que el parámetro se escriba antes de que pueda leerse y antes de que el método pueda regresar. Si C # llama a un método cuyo parámetro incluye un atributo Out() , el comstackdor, a los efectos de decidir si debe informar errores de “variable indefinida”, pretende que la variable se escribe inmediatamente antes de llamar al método. Tenga en cuenta que debido a que otros lenguajes .net no asignan el mismo significado al atributo Out() , es posible que al llamar a una rutina con un parámetro out no afecte a la variable en cuestión. Si una variable se usa como un parámetro de out antes de asignarla definitivamente, el comstackdor de C # generará código para asegurarse de que se borre en algún momento antes de ser utilizado, pero si tal variable se va y vuelve a entrar en el scope, no hay garantía que se borrará nuevamente

El ref probablemente se ahogará en nulo, ya que presumiblemente espera modificar un objeto existente. out espera nulo, ya que devuelve un nuevo objeto.

out y ref son exactamente iguales, con la excepción de que las variables de salida no tienen que ser inicializadas antes de enviarlas al abismo. No soy tan inteligente, lo descifré de la biblioteca de MSDN :).

Sin embargo, para ser más explícito acerca de su uso, el significado del modificador es que si cambia la referencia de esa variable en su código, out y ref harán que la variable que llama también cambie de referencia. En el siguiente código, la variable ceo será una referencia a la nueva Guy una vez que regrese de la llamada a doStuff. Si no fuera por ref (o fuera) la referencia no se cambiaría.

 private void newEmployee() { Person ceo = Person.FindCEO(); doStuff(ref ceo); } private void doStuff(ref Person employee) { Person newGuy = new Person(); employee = newGuy; } 

Este The Out and Ref Paramerter in C # tiene algunos buenos ejemplos.

La diferencia básica descrita es que out parámetros de out no necesitan inicializarse cuando se pasan, mientras que los parámetros de referencia sí.

Cuando se declara un parámetro de salida en la statement del método, el cuerpo del método debe asignar un valor a la variable de salida antes de regresar. Por lo tanto, es responsabilidad del método llamado asignar el valor al parámetro out antes de que regrese.

Cuando se declara un parámetro ref en el método, el argumento que se pasa al invocar el método debería tener asignado el valor. Por lo tanto, es responsabilidad del que llama asignar el valor del argumento ref antes de llamar al método.

Ellos son sutilmente diferentes.

Un parámetro de out no necesita ser inicializado por el destinatario antes de pasarlo al método. Por lo tanto, cualquier método con un parámetro de out

  • No se puede leer el parámetro antes de asignarle un valor
  • Debe asignarle un valor antes de regresar

Esto se usa para un método que necesita sobreescribir su argumento independientemente de su valor anterior.


Un parámetro ref debe ser inicializado por el destinatario antes de pasarlo al método. Por lo tanto, cualquier método con un parámetro ref

  • Puede inspeccionar el valor antes de asignarlo
  • Puede devolver el valor original, intacto

Esto se usa para un método que debe (por ejemplo) inspeccionar su valor y validarlo o normalizarlo.

ha obtenido una nueva syntax más succint en C # 7 https://docs.microsoft.com/en-us/dotnet/articles/csharp/whats-new/csharp-7#more-expression-bodied-members y aún más Las mejoras de la tupla C # 7 son una opción más elegante que utilizar ref y out en mi humilde opinión.