我不知道如果我完全失去了一些东西,但我找不到任何方法来确定参数是否通过引用传递或不使用反射。Ref参数和反射
ArgumentInfo有一个属性“IsOut”,但没有“IsRef”。我如何去获取给定MethodInfo中的所有参考参数?
我不知道如果我完全失去了一些东西,但我找不到任何方法来确定参数是否通过引用传递或不使用反射。Ref参数和反射
ArgumentInfo有一个属性“IsOut”,但没有“IsRef”。我如何去获取给定MethodInfo中的所有参考参数?
ParameterInfo[] parameters = myMethodInfo.GetParameters();
foreach(ParameterInfo parameter in parameters)
{
bool isRef = parameterInfo.ParameterType.IsByRef;
}
IsByRef只确定类型是引用类型还是值类型,据我所知,它不会告诉您类型是否通过引用传递 – 2009-10-11 21:18:33
Jorge:据我了解,“IsByRef”决定如果一个类型是通过引用传递的,而不是它是一个引用类型。例如,类型System.Object具有“IsByRef”错误,但是特殊类型System.Object&具有“IsByRef true。 – 2009-10-11 21:29:23
Jorge:你说的是IsValueType而不是IsByRef。 – 2009-10-11 21:32:58
您需要进一步检查参数的类型。例如,如果你有
void Foo(ref int bar)
则该参数的名称不会int
或Int32
(如你所料),而是Int32&
。对于每种类型,都有一个对应的by-ref-type,其中原始类型后缀为'&'。 您可以通过Type
类的IsByRef
属性进行检查。
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使差大多当类型是一个值,例如一个结构。)
ParameterType.IsByRef
将返回true
两个ref
和out
参数。
如果您有一个ParameterInfo
对象(例如,从MethodInfo.GetParameters()
),则:
out
如果parameterInfo.ParameterType.IsByRef && parameterInfo.IsOut
ref
如果parameterInfo.ParameterType.IsByRef && parameterInfo.IsOut == false
如果你不为out
参数做IsByRef
检查,那么你会错误地从System.Runtime.InteropServices
获得用[Out]
属性装饰的会员,但实际上并不是C#out
参数。
如果裁判是parameterInfo.IsIn == true && parameterInfo.IsOut == true
那么人们可能并不需要,如果parameterInfo.ParameterType.IsByRef
在所有
请使用反引号突出内联代码,并编辑您的答案,使其更具可读性(我无法阅读该句子)。 – 2016-11-03 22:07:44
当心,@PatrikHägne。 IsOut甚至不表示该参数是通过引用传递的。也就是说,这并不意味着该参数是“out”参数。正如我最近发现的,让我很懊恼。 – 2015-07-17 15:36:38
@BlairConrad:你能否详细说明你的评论? IsOut在哪些情况下并不意味着param是一个“out”参数? – RobSiklos 2016-06-28 14:03:18
@RobSiklos,当然。 [在FakeItEasy问题508中发表评论](https://github.com/FakeItEasy/FakeItEasy/issues/508#issuecomment-122147155)告诉这个肮脏的故事。一些参数用'[Out]'装饰。例如,'Stream.Read(byte [],int,int)'中的缓冲区。 – 2016-06-28 20:09:11