更新:
關於out參數,推薦讀者讀這篇文章:
.NET(C#):從IL和反射Emit更徹底地理解out參數
本文將示範通過DynamicMethod類型建立兩個動態方法,分別有ref和out參數。
首先看這樣一個簡單的方法:
static int add(ref int i, int count)
{
return i += count;
}
讓我們建立一個執行上面功能的動態方法,然後調用它。
代碼:
//+ using System.Reflection;
//+ using System.Reflection.Emit;
var dynamicMethod = new DynamicMethod("", typeof(int), new Type[] { typeof(int).MakeByRefType(), typeof(int) });
ILGenerator ilgen = dynamicMethod.GetILGenerator();
//i進棧,棧:i
ilgen.Emit(OpCodes.Ldarg_0);
//複製i,最上的i為了得到所指的整數。棧:i, i
ilgen.Emit(OpCodes.Dup);
//擷取i所代表整數。棧:i, *i
ilgen.Emit(OpCodes.Ldind_I4);
//count進棧。棧:i, *i, count
ilgen.Emit(OpCodes.Ldarg_1);
//加操作。棧:i, *i + count
ilgen.Emit(OpCodes.Add);
//賦值。棧:*i + count
ilgen.Emit(OpCodes.Stind_I4);
//重新使更新後的i進棧
ilgen.Emit(OpCodes.Ldarg_0);
//擷取*i
ilgen.Emit(OpCodes.Ldind_I4);
//結束
ilgen.Emit(OpCodes.Ret);
接著,調用這個動態方法:
//參數:
var i = -3;
var count = 10;
var arg = new object[] { i, count };
//調用動態方法
int result = (int)dynamicMethod.Invoke(null, arg);
//輸出結果
Console.WriteLine(result);
Console.WriteLine(arg[0]);
輸出:
7
7
OK,傳回值和第一個參數結果都是7。
接下來看一個out參數的:
將建立一個這樣的方法:
static void outObject(out object obj)
{
obj = "hehe";
}
代碼:
//+ using System.Reflection;
//+ using System.Reflection.Emit;
var dynamicMethod = new DynamicMethod("", null, new Type[] { typeof(object).MakeByRefType() });
//設定ref參數為out。(事實上不用這句程式也會成功執行)
dynamicMethod.DefineParameter(1, ParameterAttributes.Out, "obj");
ILGenerator ilgen = dynamicMethod.GetILGenerator();
//obj進棧
ilgen.Emit(OpCodes.Ldarg_0);
//把hehe進棧
ilgen.Emit(OpCodes.Ldstr, "hehe");
//賦值
ilgen.Emit(OpCodes.Stind_Ref);
//退出
ilgen.Emit(OpCodes.Ret);
//參數:
var arg = new object[] { null };
//調用動態方法
dynamicMethod.Invoke(null, arg);
//輸出結果
Console.WriteLine(arg[0]);
輸出:
hehe