2011-01-24 4 views
7

En System.Runtime.InteropServices existe el atributo <Out()>. ¿Pero para qué sirve? Me gustaría que pudieras usar el siguiente ejemplo como base para tus respuestas.El <Out()> Atributo. ¿Qué utilidad tiene el servir?

Shared Sub Add(ByVal x As Integer, ByVal y As Integer, <Out()> ByRef Result As Integer) 
    Result = x + y 
End Sub 

Respuesta

7

El propósito de ese atributo es doble:

  • de gestión de llamadas in situ , ya sea para hacer cumplir la inicialización de variables o no
  • Marshalling

Si se va a llamar a ese método de C#, o un lenguaje similar con una semántica similar, tal parámetro sería conocido a el compilador no necesita un valor inicial.

En otras palabras, se puede hacer esto:

int a; 
CallSomeMethodWithOutParameter(out a); 

y el compilador sabe que no hay necesidad de asegurar que a ya tiene un valor antes de hacer la llamada.

Por otra parte, sin el atributo, se necesitaría la siguiente, de nuevo en C#:

int a = 0;        // <-- notice initialization here 
CallSomeMethodWithOutParameter(ref a); // <-- and ref here 

El otro propósito es para llamadas a métodos que serán movilizados en un contexto de llamada diferente, por ejemplo a través P/Invocar a un dominio de aplicación diferente oa un servicio web para notificar a las rutinas de clasificación que el parámetro en cuestión contendrá un valor cuando el método retorne, pero no es necesario pasar ningún valor al método al llamarlo .

Esto puede marcar la diferencia cuando los parámetros y valores devueltos deben empaquetarse y transportarse a la ubicación remota donde se realiza la llamada real.

En otras palabras, si se va a especificar que en una llamada al método utilizado por P/Invoke, ninguna de clasificación se llevará a cabo del valor del parámetro existente cuando el método se llama, pero cuando el método vuelve su el valor vuelve a su código de llamada.

Tenga en cuenta que esta optimización depende de la rutina de clasificación para usar, o no, estos son los detalles de implementación. El atributo simplemente le dice a la rutina qué parámetros puede hacer con eso, no es una instrucción que siempre se seguirá.

0

No sé acerca de VB, pero asumiendo que es equivalente a C# 's out palabra clave:

Se comporta igual que ref pero no requiere que la persona que llama para inicializar la variable se pasa al parámetro out porque la función no lo leerá

Y probablemente tenga un efecto en las referencias si utiliza COM oder p-invoke.

3

Significa que el parámetro se ve como un parámetro de "salida" por C#, por un lado. En ese caso, el compilador de C# asumirá que:

  • Cualquier valor actual de la variable pasada por referencia es irrelevante, misiones de manera definitiva no importa
  • El se se les ha asignado un valor apropiado variables cuando el método retorna, a menos que haya una excepción, por lo que definitivamente se asigna al final de la declaración.

Otros idiomas pueden optar por utilizar el atributo [Out] de diferentes maneras, por supuesto, pero ese tipo de interpretación es la más natural. Básicamente dice que el parámetro es casi como un valor de retorno extra. (Hay un montón de diferencias, por supuesto, de diferentes grados de sutileza, pero eso es lo general sensación de un parámetro de salida.)

+0

¿No importaría C# solo si compilara el código en cuestión? ¿No es "ref" y "out" idéntico en el sitio de llamada? - no importa :) –

+0

En realidad, lo que significa es que si la variable no se escribió antes de llamar a la rutina en cuestión, el compilador insertará código en silencio para inicializar la ubicación de almacenamiento que contiene la variable en lugar de quejarse (no hay garantía de dónde se colocará dicho código, ni hay ninguna garantía de que una variable que abandona y vuelve a entrar en el alcance no continúe usando la misma ubicación de almacenamiento sin reinicialización). El compilador realmente no puede suponer que la variable fue escrita, ya que no puede estar seguro de que la rutina llamada realmente la escriba. – supercat

+0

@supercat: Depende del nivel al que estemos considerando las cosas. El nivel "verificar que tu código fuente es válido" * supone * que la variable fue escrita. El nivel "emitir IL" no lo hace, aunque una implementación diferente dirigida a una plataforma diferente * podría * ser capaz de hacerlo. –

2

Se utiliza en tipos ComVisible para indicar que la biblioteca de tipos COM generada debe decorar el parámetro con el atributo [out].

0

Al aplicar a los parámetros del método y los valores de retorno, este atributo controla la dirección de cálculo de referencias, por lo que se conoce como atributos direccionales. [OutAttribute] le dice al CLR que se margine de regreso del llamante a la persona que llama a su regreso. Tanto la persona que llama como la persona que llama pueden ser códigos administrados o no administrados. Por ejemplo, en una llamada P/Invoke, el código administrado llama al código no administrado. Sin embargo, en un P/Invoke inverso, el código no administrado podría llamar al código administrado a través de un puntero de función.

Hay casos en que se ignorará [OutAttribute]. Por ejemplo, [OutAttribute]int no tiene sentido, por lo que el CLR simplemente ignora el [OutAttribute]. Lo mismo se aplica a la cadena [OutAttribute] porque la cadena es inmutable.

Por lo tanto, para su ejemplo, este atributo no tiene sentido. Más acerca de este atributo y el atributo <In()> correlacionado puede encontrar here.

Cuestiones relacionadas