Created
October 30, 2017 10:42
-
-
Save weltkante/94652de66940d494cdcf61e3a62a4b0f to your computer and use it in GitHub Desktop.
test ref-return and dynamic code generation
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
using System; | |
using System.Reflection; | |
using System.Reflection.Emit; | |
namespace TestProgram | |
{ | |
delegate ref int GetRefIntoArrayDelegate(int[] array, int index); | |
class Program | |
{ | |
static int[] _values = new int[8]; | |
static void Main() | |
{ | |
Console.WriteLine("Testing C# implementation"); | |
Test1(); // calls C# implementation directly | |
Console.WriteLine("Testing C# implementation via delegate"); | |
Test2(() => GetRefIntoArrayImpl); // uses C# implementation via delegate | |
Console.WriteLine("Testing dynamic assembly"); | |
Test2(() => CreateDynamicAssemblyImpl()); // uses dynamic assembly delegate | |
Console.WriteLine("Testing dynamic method"); | |
Test2(() => CreateDynamicMethodImpl()); // uses dynamic method delegate | |
} | |
static void Test1() | |
{ | |
try | |
{ | |
InitValues(); | |
ref int p = ref GetRefIntoArrayImpl(_values, 4); | |
p = 40; | |
PrintValues(); | |
} | |
catch (Exception ex) | |
{ | |
Console.Error.WriteLine(ex.Message); | |
} | |
} | |
static void Test2(Func<GetRefIntoArrayDelegate> factory) | |
{ | |
try | |
{ | |
var f = factory(); | |
InitValues(); | |
ref int p = ref f(_values, 4); | |
p = 40; | |
PrintValues(); | |
} | |
catch (Exception ex) | |
{ | |
Console.Error.WriteLine(ex); | |
} | |
} | |
static void InitValues() | |
{ | |
for (int i = 0; i < _values.Length; i++) | |
_values[i] = i; | |
} | |
static void PrintValues() | |
{ | |
Console.WriteLine(string.Join(", ", _values)); | |
} | |
static ref int GetRefIntoArrayImpl(int[] array, int index) | |
{ | |
/* | |
.method private hidebysig static | |
int32& GetRefIntoArrayImpl ( | |
int32[] 'array', | |
int32 index | |
) cil managed | |
{ | |
// Method begins at RVA 0x2149 | |
// Code size 8 (0x8) | |
.maxstack 8 | |
IL_0000: ldarg.0 | |
IL_0001: ldarg.1 | |
IL_0002: ldelema [System.Runtime]System.Int32 | |
IL_0007: ret | |
} // end of method Program::GetRefIntoArrayImpl | |
*/ | |
return ref array[index]; | |
} | |
static GetRefIntoArrayDelegate CreateDynamicAssemblyImpl() | |
{ | |
var name = new AssemblyName("GeneratedCodeContainer"); | |
var assembly = AssemblyBuilder.DefineDynamicAssembly(name, AssemblyBuilderAccess.RunAndCollect); | |
var module = assembly.DefineDynamicModule(name.Name); | |
var type = module.DefineType("GeneratedMethodContainer", TypeAttributes.Public); | |
var method = type.DefineMethod("GetRefIntoArray_DynamicAssemblyImpl", MethodAttributes.Public | MethodAttributes.Static, typeof(int).MakeByRefType(), new[] { typeof(int[]), typeof(int) }); | |
var code = method.GetILGenerator(); | |
code.Emit(OpCodes.Ldarg_0); | |
code.Emit(OpCodes.Ldarg_1); | |
code.Emit(OpCodes.Ldelema, typeof(int)); | |
code.Emit(OpCodes.Ret); | |
return (GetRefIntoArrayDelegate)type.CreateType().GetMethod(method.Name).CreateDelegate(typeof(GetRefIntoArrayDelegate)); | |
} | |
static GetRefIntoArrayDelegate CreateDynamicMethodImpl() | |
{ | |
var method = new DynamicMethod("GetRefIntoArray_DynamicMethodImpl", typeof(int).MakeByRefType(), new[] { typeof(int[]), typeof(int) }); | |
var code = method.GetILGenerator(); | |
code.Emit(OpCodes.Ldarg_0); | |
code.Emit(OpCodes.Ldarg_1); | |
code.Emit(OpCodes.Ldelema, typeof(int)); | |
code.Emit(OpCodes.Ret); | |
return (GetRefIntoArrayDelegate)method.CreateDelegate(typeof(GetRefIntoArrayDelegate)); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment