我不知道如果我完全失去了一些東西,但我找不到任何方法來確定參數是否通過引用傳遞或不使用反射。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