参考参数和反射

时间:2009-10-11 21:01:28

标签: c# reflection

我不确定我是否完全错过了这里的内容,但我找不到任何方法来确定参数是否通过引用传递,或者不使用反射。

ArgumentInfo有一个属性“IsOut”,但没有“IsRef”。我如何获得给定MethodInfo中的所有参考参数?

5 个答案:

答案 0 :(得分:38)

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

答案 1 :(得分:9)

对于ParameterType.IsByRef true参数,

ref将返回out

如果您有ParameterInfo个对象(例如来自MethodInfo.GetParameters()),那么:

  • 如果out
  • ,参数为parameterInfo.ParameterType.IsByRef && parameterInfo.IsOut
  • 如果ref
  • ,参数为parameterInfo.ParameterType.IsByRef && parameterInfo.IsOut == false

如果您未IsByRef检查out个参数,那么您将错误地从[Out]获取使用System.Runtime.InteropServices属性修饰的成员但实际上并不是C#out参数。

答案 2 :(得分:7)

您需要进一步检查参数的类型。例如,如果你有

void Foo(ref int bar)

然后参数的名称将不是intInt32(正如您可能预期的那样),而是Int32&。对于每种类型,都有一个对应的by-ref-type,其中原始类型后缀为'&'。 您可以通过IsByRef类的Type属性进行检查。

答案 3 :(得分:1)

如果参数的声明带有ByRef关键字,则ParameterInfo.ParameterType.IsByRef返回true;如果声明带有ByVal关键字,则返回false(无论参数的类型是否为by-value(例如,结构) )或通过引用(例如,类))。

为了说明,请考虑以下结构和类(我正在使用VB代码):

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

Public Class MyClass1
End Class

假设您有以下方法为上面定义的结构和类获取ByVal和ByRef参数(请注意,从VB 2012开始,您可以省略ByVal关键字,因为它是默认值):

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

现在,以下代码测试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

您将获得以下输出:

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

如您所见,ParameterInfo.ParameterType.IsByRef为参数s2和c2返回true,因为它们是使用ByRef关键字定义的,即使其中一个是结构(值类型)而另一个是类(引用) -类型);并为使用ByVal关键字定义的参数返回false。

但请注意,ByVal关键字并不意味着所有参数都将作为副本传递。即使使用了这个关键字(ByVal),如果类型是引用(例如,类),则参数将通过引用传递,就像使用了ByRef关键字一样。也就是说,上述方法P的c1和c2将通过引用传递,这意味着如果P将字段或属性更改为c1或c2,则更改将反映给调用者。 (ByVal和ByRef主要在类型为值时产生差异,例如结构。)

答案 4 :(得分:0)

如果ref为parameterInfo.IsIn == true && parameterInfo.IsOut == true 然后可能不需要parameterInfo.ParameterType.IsByRef