2009-10-11 11 views
29

No estoy seguro de si me falta algo aquí, pero no puedo encontrar ninguna forma de determinar si un parámetro se pasa por referencia o no mediante el uso de la reflexión.Ref. Parámetros y reflexión

ArgumentInfo tiene una propiedad "IsOut", pero no "IsRef". ¿Cómo podría obtener todos los parámetros de referencia en una MethodInfo determinada?

+0

cuidado, @Patrik Hagne. IsOut ni siquiera significa que el parámetro se pasa por referencia. Es decir, no significa que el parámetro sea un parámetro de "salida". Como descubrí recientemente, para mi disgusto. –

+0

@BlairConrad: ¿pueden dar más detalles sobre su comentario anterior? ¿En qué situaciones IsOut no significa que el param es un parámetro de "salida"? – RobSiklos

+0

@RobSiklos, claro. La sórdida historia se cuenta en [un comentario en la edición FakeItEasy 508] (https://github.com/FakeItEasy/FakeItEasy/issues/508#issuecomment-122147155). Algunos parámetros están decorados con '[Out]'. Por ejemplo, el búfer en 'Stream.Read (byte [], int, int)'. –

Respuesta

35
ParameterInfo[] parameters = myMethodInfo.GetParameters(); 
foreach(ParameterInfo parameter in parameters) 
{ 
    bool isRef = parameterInfo.ParameterType.IsByRef; 
} 
+2

IsByRef no solamente determinar si el tipo es un tipo de referencia o un valor Tipo medida de lo que puedo decir, que no te dice si el Tipo de si ser pasada por referencia –

+5

Jorge: Por lo que yo puedo entenderlo "IsByRef" determina si un tipo se pasa por referencia, no si es un tipo de referencia. Por ejemplo, el tipo System.Object tiene "IsByRef", sin embargo el tipo falso, System.Object especial y tiene "IsByRef cierto –

+9

Jorge:.. Lo que estamos hablando es de' IsValueType', no 'IsByRef' –

7

Necesita examinar el tipo de su parámetro más. Por ejemplo, si tiene

void Foo(ref int bar) 

entonces el nombre del parámetro no habría int o Int32 (como se podría haber esperado) pero en vez Int32&. Para cada tipo hay un corresponsal de tipo ref, donde el tipo original tiene el sufijo '&'. Puede verificar esto a través de la propiedad IsByRef de la clase Type.

1

ParameterInfo.ParameterType.IsByRef devuelve verdadero si la declaración del parámetro es con la palabra clave ByRef, y devuelve falso si la declaración es con la palabra clave ByVal (independientemente de si el tipo del parámetro es por valor (por ejemplo, estructura) o referencia (por ejemplo, clase)).

Como ejemplo, consideremos la siguiente estructura y la clase (estoy usando el código VB):

' Empty structure and class, just for illustration. 
Public Structure MyStruct 
End Structure 

Public Class MyClass1 
End Class 

Y supongamos que tiene el siguiente método que toma ByVal y ByRef argumentos a favor de la estructura y la clase definida anteriormente (tenga en cuenta que a partir de 2012 VB, puede omitir la palabra clave ByVal, ya que es el valor por defecto):

Public Sub P(s1 As MyStruct, ByRef s2 As MyStruct, c1 As MyClass1, ByRef c2 As MyClass1) 
End Sub 

Ahora el siguiente código prueba el método ParameterInfo.ParameterType.IsByRef:

Private Sub Button1_Click(sender As System.Object, e As System.EventArgs) Handles Button1.Click 
     ' Reflect on method P: 
    Dim mi As MethodInfo = Me.GetType.GetMethod("P") 
    ' Iterate all parameters, and call its ParameterType.IsByRef method: 
    For Each pi As ParameterInfo In mi.GetParameters 
     If **pi.ParameterType.IsByRef** _ 
     Then Console.WriteLine(pi.Name & " is ByRef") _ 
     Else Console.WriteLine(pi.Name & " is ByVal") 
    Next 
End Sub 

obtendrá el siguiente resultado:

s1 is ByVal 
s2 is ByRef 
c1 is ByVal 
c2 is ByRef 

Como se puede ver, ParameterInfo.ParameterType.IsByRef devuelve verdadero para los argumentos s2 y c2, ya que se definen con la palabra clave ByRef, a pesar de que uno de ellos son una estructura (tipo de valor) y la otra es una clase (tipo de referencia); y devuelve falso para los argumentos definidos con la palabra clave ByVal.

Tenga en cuenta, sin embargo, que la palabra clave ByVal no significa que todos los argumentos se pasarán como una copia. Incluso si se utiliza esta palabra clave (ByVal), si el tipo es por referencia (por ejemplo, clase), el argumento se pasará por referencia, como si se utilizara la palabra clave ByRef. Es decir, c1 y c2 del método P anterior se pasarán ambos por referencia, lo que significa que si P cambia un campo o propiedad a c1 o c2, los cambios se reflejarán en la persona que llama. (ByVal y ByRef hacen diferencia sobre todo cuando el tipo es un valor, tal como una estructura.)

5

ParameterType.IsByRef volverá true para ambos refyout parámetros.

Si tiene un objeto ParameterInfo (p. Ej.de MethodInfo.GetParameters()), entonces:

  • El parámetro es out si parameterInfo.ParameterType.IsByRef && parameterInfo.IsOut
  • El parámetro es ref si parameterInfo.ParameterType.IsByRef && parameterInfo.IsOut == false

Si usted no hace el cheque IsByRef para out parámetros, entonces usted incorrectamente que los miembros decoradas con el atributo de [Out]System.Runtime.InteropServices pero que no son en realidad C# out parámetros.

0

si ref es parameterInfo.IsIn == true && parameterInfo.IsOut == true entonces uno podría no necesitar si parameterInfo.ParameterType.IsByRef en absoluto

+0

Utilice los marcadores para resalte el código en línea y edite su respuesta para que sea más legible (no puedo leer la oración). –

Cuestiones relacionadas