2009-10-11 89 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