C # proporciona la ref
y la out
palabra clave para hacer que los argumentos se pasen por referencia. La semántica de los dos es muy similar. La única diferencia está en la inicialización de la variable con bridas:
ref
requiere que la variable se inicialice antes de pasarla a la función,out
no lo hace.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 los mismos, y su uso demasiado frecuente es considerado un olor a código (aunque hay casos de uso válidos como el TryParse
y los TryGetValue
patrones).
Debido a esto, alguien podría explicar, ¿por qué hay dos herramientas muy similares en C # para casos de uso tan limitados?
Además, en MSDN , se afirma que tienen un comportamiento de tiempo de ejecución diferente:
Aunque las palabras clave ref y out provocan un comportamiento de tiempo de ejecución diferente, no se consideran parte de la firma del método en tiempo de compilación.
¿Cómo es diferente su comportamiento en tiempo de ejecución?
Conclusión
Ambas respuestas parecen correctas, gracias a ambos. Acepté jmoreno 's porque es más explícito.
fuente
ref
en C ++; a punteros al puntero de objeto (o primitivo) en cuestión. es decir,Int32.TryParse(myStr, out myInt)
(C #) se "ejecuta" de la misma manera que loint32_tryParse(myStr, &myInt)
haría (C); La única diferencia son algunas restricciones impuestas por el compilador para evitar errores. (No voy a publicar esto como respuesta porque puedo estar equivocado acerca de cómo funciona esto detrás de escena, pero así es como imagino que funciona [porque tiene sentido])Respuestas:
En el momento en que se hizo esta pregunta, el artículo de MSDN era sutilmente incorrecto ( desde entonces se ha corregido ). En lugar de "causar un comportamiento diferente" debería ser "requiere un comportamiento diferente".
En particular, el compilador impone diferentes requisitos para las dos palabras clave, a pesar de que se utiliza el mismo mecanismo (IL) para habilitar el comportamiento.
fuente
out
parámetro o no asignar unref
parámetro, pero la IL que emite es solo una referencia de cualquier manera. ¿Es eso correcto?out T
yref T
se representan de forma idéntica en otros lenguajes CLI como VB.Net o C ++ / CLI.Aquí hay una reseña interesante sobre el tema que puede responder a su pregunta:
http://www.dotnetperls.com/ref
punto de interés:
"La diferencia entre ref y out no está en Common Language Runtime, sino en el lenguaje C # mismo".
actualizar:
el desarrollador senior de mi trabajo simplemente corroboró la respuesta de @ jmoreno, ¡así que asegúrese de leerla!
fuente
string
tiene que ver con todo esto?Tiempo de ejecución ? Absolutamente ninguno. No puede sobrecargar un método con los mismos parámetros que difieren solo por palabra clave ref o out.
Intente compilar esto y obtendrá un error de compilación "El método con la misma firma ya está declarado":
Para responder a esta pregunta: "... ¿por qué hay dos herramientas muy similares en C # para casos de uso tan limitados?"
Desde el punto de vista de la legibilidad del código y la API, hay una gran diferencia. Como consumidor de la API, sé que cuando se usa "fuera", la API no depende del parámetro de salida. Como desarrollador de API, prefiero "out" y uso "ref" solo cuando es absolutamente (¡RARAMENTE!) Necesario. Vea esta referencia para una gran discusión:
/programming/1516876/when-to-use-ref-vs-out
Información de soporte: compilé el siguiente método y lo desarme. Utilicé las palabras clave ref y out (en este ejemplo), pero el código de ensamblaje no cambió excepto por una referencia de dirección como era de esperar:
00000000 empuje ebp
00000001 mov ebp, esp
00000003 empuje edi
00000004 empuje 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 llame al 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?
fuente