36

I'm not sure if I'm totally missing something here but I can't find any way to determine if a parameter is passed by reference or not by using reflection.

ArgumentInfo has a property "IsOut", but no "IsRef". How would I go about to get all reference parameters in a given MethodInfo?

Patrik Hägne
  • 16,751
  • 5
  • 52
  • 60
  • Beware, @Patrik Hägne. IsOut doesn't even mean that the parameter is passed by reference. That is, it doesn't mean that the parameter is an "out" parameter. As I recently discovered, much to my chagrin. – Blair Conrad Jul 17 '15 at 15:36
  • 1
    @BlairConrad : can you elaborate on your above comment? In which situations does IsOut not mean that the param is an "out" parameter? – RobSiklos Jun 28 '16 at 14:03
  • @RobSiklos, sure. The sordid story is told in [a comment in FakeItEasy issue 508](https://github.com/FakeItEasy/FakeItEasy/issues/508#issuecomment-122147155). Some parameters are decorated with `[Out]`. For example, the buffer in `Stream.Read(byte[], int, int)`. – Blair Conrad Jun 28 '16 at 20:09
  • @BlairConrad, cool case. I did some checking and found that real `out` params have both `IsOut` and `ParameterType.IsByRef`. See my answer to this question which I just posted. – RobSiklos Jun 29 '16 at 21:08

5 Answers5

43
ParameterInfo[] parameters = myMethodInfo.GetParameters();
foreach(ParameterInfo parameter in parameters)
{
    bool isRef = parameterInfo.ParameterType.IsByRef;
}
Rex M
  • 142,167
  • 33
  • 283
  • 313
  • 2
    IsByRef does only determine if the Type is a reference Type or a value Type as far as I can tell, it does not tell you if the Type if being pass by reference – Jorge Córdoba Oct 11 '09 at 21:18
  • 5
    Jorge: As far as I can understand it "IsByRef" determines if a type is passed by reference, not if it's a reference type. For example the type System.Object has "IsByRef" false, however the special type System.Object& has "IsByRef true. – Patrik Hägne Oct 11 '09 at 21:29
  • 13
    Jorge: What you are talking about is `IsValueType`, not `IsByRef`. – Mehrdad Afshari Oct 11 '09 at 21:32
  • I'm in the process of working with an interop generated assembly which has only method signatures using primitive types, and even though the IsByRef property returns true if the parameter is marked with ref, it also return true if the parameter is marked as out. So IsByRef can't really be used to find out if a parameter has the ref keyword and the same applies to the out. – MeTitus Oct 23 '15 at 12:20
  • 3
    `IsByRef` also returns true for `out` parameters. See my answer to this question for how to differentiate. – RobSiklos Jun 29 '16 at 21:14
25

ParameterType.IsByRef will return true for both ref and out parameters.

If you have a ParameterInfo object (e.g. from MethodInfo.GetParameters()), then:

  • The param is out if parameterInfo.ParameterType.IsByRef && parameterInfo.IsOut
  • The param is ref if parameterInfo.ParameterType.IsByRef && parameterInfo.IsOut == false

If you don't do the IsByRef check for out parameters, then you'll incorrectly get members decorated with the [Out] attribute from System.Runtime.InteropServices but which aren't actually C# out parameters.

RobSiklos
  • 8,348
  • 5
  • 47
  • 77
7

You need to examine the type of your parameter further. For example if you have

void Foo(ref int bar)

then the name of the parameter wouldn't be int or Int32 (as you might have expected) but instead Int32&. For every type there is a correspondent by-ref-type where the original type is suffixed by a '&'. You can check this via the IsByRef property of the Type class.

Christian Rodemeyer
  • 2,001
  • 1
  • 19
  • 22
1

ParameterInfo.ParameterType.IsByRef returns true if the declaration of the parameter is with the ByRef keyword, and returns false if the declaration is with the ByVal keyword (regardless of whether the type of the parameter is by-value (e.g., structure) or by-reference (e.g., class)).

To illustrate, consider the following structure and class (I'm using VB code):

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

Public Class MyClass1
End Class

And suppose you have the following method that takes ByVal and ByRef arguments for the structure and class defined above (note that starting with VB 2012, you can omit the ByVal keyword as it is the default):

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

Now the following code tests the ParameterInfo.ParameterType.IsByRef method:

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

You'll get the following output:

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

As you can see, ParameterInfo.ParameterType.IsByRef returns true for arguments s2 and c2 because they are defined with the ByRef keyword, even though one of them is a structure (value-type) and the other is a class (reference-type); and returns false for the arguments defined with the ByVal keyword.

Note, however, that the ByVal keyword does not mean that all arguments would be passed as a copy. Even if this keyword (ByVal) is used, if the type is by-reference (e.g., class), the argument would be passed by reference, as if the ByRef keyword were used. That is, c1 and c2 of method P above will BOTH be passed by reference, which means that if P changes a field or property to c1 or c2, the changes will be reflected to the caller. (ByVal and ByRef make difference mostly when the type is a value, such as a structure.)

1

if ref is parameterInfo.IsIn == true && parameterInfo.IsOut == true then one might not need if parameterInfo.ParameterType.IsByRef at all

Turbofish
  • 11
  • 2
  • Please, use backticks to highlight inline code, and edit your answer to make it more readable (I cannot read the sentence). – Andrey Moiseev Nov 03 '16 at 22:07