利用反射呼叫方法時,處理ref,out引數需要注意的問題
阿新 • • 發佈:2019-02-15
專案中如下的泛型方法,因為要在執行時,動態指定型別引數,所以要利用反射來實現。
public static TR Deserialize<TR>(byte[] source, ref int offset)
一般做法如下:
// 變數 type是該方法所在型別的執行時Type // model是已經定義的例項 MethodInfo genericMethod = type.GetMethod("Deserialize", BindingFlags.Public | BindingFlags.Static); MethodInfo mi = genericMethod.MakeGenericMethod(model.GetType());
反射拿到MethodInfo之後,即可呼叫方法
// int p
// byte[] source
// object result
result = mi.Invoke(null, new object[]{source, p});
注意這裡的呼叫方法傳的引數,形參offset並沒有像直接呼叫方法那樣指定ref修飾符,像ref,out這樣的引數修飾符在利用反射呼叫方法時是不需要指定的。
回到我們的主題,我們希望方法呼叫之後,我們傳的引數p的值被修改了,事實上,我們會發現,引數p的值並未被改變。
MSDN上面,.net
framework 4.5版本中,特別提到了這一點,ref和out引數可能被修改。那我們的問題出在哪裡了呢?
問題出在了我們傳引數的過程。上面的方法呼叫,引數被裝入陣列,由Invoke方法傳遞給mi指向的方法。我們構造object陣列的初始化過程,是值傳遞的。另一方面,這個object陣列在呼叫完成後,就被丟掉了。將上述程式碼改成如下寫法:
object[] args = new object[]{source, p};
result = mi.Invoke(null, args);
p = (int)args[1];
然後,我們就會發現,被修改的引數,其實在引數陣列中好好的放著呢。