¿Cuál es la diferencia entre ref y out en tiempo de ejecución?

13

C # proporciona las palabras clave ref y out para hacer que los argumentos se pasen por referencia. La semántica de los dos es muy parecida. La única diferencia está en la inicialización de la variable flage:

  • ref requiere que la variable se inicialice antes de pasarla a la función, out no.
  • out requiere que la variable se inicialice dentro de la función, ref no.

Los casos de uso de estas dos palabras clave también son casi iguales, y su uso demasiado frecuente se considera un olor de código (aunque existen casos de uso válidos como los patrones TryParse y TryGetValue ).

Debido a esto, alguien podría explicar, ¿por qué hay dos herramientas muy similares en C # para casos de uso tan estrechos?

También, en MSDN , se afirma que tienen un comportamiento diferente en tiempo de ejecución:

  

Aunque las palabras clave ref y out causan un comportamiento diferente en el tiempo de ejecución, no se consideran parte de la firma del método en el momento de la compilación.

¿En qué se diferencia su comportamiento en tiempo de ejecución?

Conclusión

Ambas respuestas parecen correctas, gracias a las dos. Acepté los jmoreno porque es más explícito.

    
pregunta Gábor Angyal 10.02.2015 - 11:04

3 respuestas

9

El artículo de MSDN es sutilmente incorrecto. En lugar de "causar un comportamiento diferente" debería ser "requiere un comportamiento diferente".

En particular, el compilador impone requisitos diferentes para las dos palabras clave, aunque se utiliza el mismo mecanismo (IL) para habilitar el comportamiento.

    
respondido por el jmoreno 10.02.2015 - 16:34
4

aquí hay una interesante reseña sobre el tema que puede responder a su pregunta:

enlace

punto de interés:

"La diferencia entre referencia y salida no está en Common Language Runtime, sino en el lenguaje C # en sí".

actualizacion :

el desarrollador senior en mi trabajo acaba de corroborar la respuesta de @jmoreno, ¡así que asegúrate de leerla!

    
respondido por el Dan Beaulieu 10.02.2015 - 14:08
1

Runtime ? Absolutamente ninguno. No puede sobrecargar un método con los mismos parámetros que difieren solo por la palabra clave ref o out.

Intenta compilar esto y obtendrás un error de compilación "El método con la misma firma ya está declarado":

    private class MyClass
    {
        private void DoSomething(out int param)
        {
        }
        private void DoSomething(ref int param)
        {
        }
    }

Para responder a esta pregunta:   "... ¿por qué hay dos herramientas muy similares en C # para casos de uso tan estrechos?"

Desde el punto de vista de API y legibilidad del código, hay una gran diferencia. Como consumidor de la API, sé que cuando se usa "out", la API no depende del parámetro out. Como desarrollador de API, prefiero "out" y uso "ref" solo cuando sea absolutamente (¡RARAMENTE!) Necesario. Vea esta referencia para una gran discusión:

enlace

Información de apoyo: Compilé el siguiente método y lo desarmé. Utilicé las palabras clave ref y out (en este ejemplo), pero el código de ensamblaje no se modificó, excepto por una referencia de dirección, como es de esperar:

    private class MyClass
    {
        internal void DoSomething(out int param)
        {
            param = 0;
        }
    }

00000000 push ebp
00000001 mov ebp, esp
00000003 push edi
00000004 push esi
00000005 empuje ebx
00000006 sub esp, 34h
00000009 xor eax, eax
0000000b mov dword ptr [ebp-10h], eax
0000000e mov dword ptr [ebp-1Ch], eax
00000011 mov dword ptr [ebp-3Ch], ecx
00000014 mov dword ptr [ebp-40h], edx
00000017 cmp dword ptr ds: [008B1710h], 0
0000001e je 00000025
00000020 llamar 6E6B601E
00000025 nop
                param = 0;
00000026 mov eax, dword ptr [ebp-40h]
00000029 xor edx, edx
0000002b mov dword ptr [eax], edx
            }
0000002d nop
0000002e lea esp, [ebp-0Ch]
00000031 pop ebx
00000032 pop esi
00000033 pop edi
00000034 pop ebp
00000035 ret

¿Estoy leyendo el ensamblaje correctamente?

    
respondido por el Shmoken 12.02.2015 - 02:20

Lea otras preguntas en las etiquetas