2009-10-11 90 views
29

我不知道如果我完全失去了一些东西,但我找不到任何方法来确定参数是否通过引用传递或不使用反射。Ref参数和反射

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

+0

当心,@PatrikHägne。 IsOut甚至不表示该参数是通过引用传递的。也就是说,这并不意味着该参数是“out”参数。正如我最近发现的,让我很懊恼。 – 2015-07-17 15:36:38

+0

@BlairConrad:你能否详细说明你的评论? IsOut在哪些情况下并不意味着param是一个“out”参数? – RobSiklos 2016-06-28 14:03:18

+0

@RobSiklos,当然。 [在FakeItEasy问题508中发表评论](https://github.com/FakeItEasy/FakeItEasy/issues/508#issuecomment-122147155)告诉这个肮脏的故事。一些参数用'[Out]'装饰。例如,'Stream.Read(byte [],int,int)'中的缓冲区。 – 2016-06-28 20:09:11

回答

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

IsByRef只确定类型是引用类型还是值类型,据我所知,它不会告诉您类型是否通过引用传递 – 2009-10-11 21:18:33

+5

Jorge:据我了解,“IsByRef”决定如果一个类型是通过引用传递的,而不是它是一个引用类型。例如,类型System.Object具有“IsByRef”错误,但是特殊类型System.Object&具有“IsByRef true。 – 2009-10-11 21:29:23

+9

Jorge:你说的是IsValueType而不是IsByRef。 – 2009-10-11 21:32:58

7

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

void Foo(ref int bar) 

则该参数的名称不会intInt32(如你所料),而是Int32&。对于每种类型,都有一个对应的by-ref-type,其中原始类型后缀为'&'。 您可以通过Type类的IsByRef属性进行检查。

1

ParameterInfo.ParameterType.IsByRef返回true,如果参数的声明与ByRef关键字一致,则返回false;如果声明与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 

正如你所看到的,因为它们与ByRef关键字定义ParameterInfo.ParameterType.IsByRef返回参数S2和C2如此,即使一个他们是一个结构(value-type),另一个是一个类(reference-type);并且用ByVal关键字定义的参数返回false。

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

5

ParameterType.IsByRef将返回true两个refout参数。

如果您有一个ParameterInfo对象(例如,从MethodInfo.GetParameters()),则:

  • 的参数是out如果parameterInfo.ParameterType.IsByRef && parameterInfo.IsOut
  • 的参数是ref如果parameterInfo.ParameterType.IsByRef && parameterInfo.IsOut == false

如果你不为out参数做IsByRef检查,那么你会错误地从System.Runtime.InteropServices获得用[Out]属性装饰的会员,但实际上并不是C#out参数。

0

如果裁判是parameterInfo.IsIn == true && parameterInfo.IsOut == true 那么人们可能并不需要,如果parameterInfo.ParameterType.IsByRef在所有

+0

请使用反引号突出内联代码,并编辑您的答案,使其更具可读性(我无法阅读该句子)。 – 2016-11-03 22:07:44