IL 수준에서는 블록의 개념이 없으므로 두식이 모두 같은 (또는 매우 유사한) IL 코드가 될 것으로 기대합니다.
이 사실을 확인하려면 Reflection.Emit 및 CompileToMethod()
을 사용하여 별도의 방법으로 두 옵션이 모두있는 어셈블리를 만들 수 있습니다. 그런 다음 코드는 실제로 동일한 지 확인하기 위해 ILDASM을 사용하여 두 방법의 IL 볼 수 있습니다 :
.locals init (
[0] class [ConsoleApplication1]ConsoleApplication1.A a,
[1] class [ConsoleApplication1]ConsoleApplication1.B b)
L_0000: newobj instance void [ConsoleApplication1]ConsoleApplication1.A::.ctor()
L_0005: stloc.0
L_0006: ldloc.0
L_0007: newobj instance void [ConsoleApplication1]ConsoleApplication1.B::.ctor(class [ConsoleApplication1]ConsoleApplication1.A)
L_000c: stloc.1
L_000d: ret
과 같이 할 수있는 어셈블리를 생성하는 코드 : 실제로 수행하는
var var1 = Expression.Variable(typeof(A), "var1");
var var2 = Expression.Variable(typeof(B), "var2");
Expression<Action> withBlocks =
Expression.Lambda<Action>(
Expression.Block(
new[] { var1, var2 },
Expression.Block(
Expression.Block(
Expression.Assign(
var1,
Expression.New(typeof(A).GetConstructors().Single())),
var1),
Expression.Block(
Expression.Assign(
var2,
Expression.New(
typeof(B).GetConstructors().Single(), var1)),
var2))));
Expression<Action> withoutBlocks =
Expression.Lambda<Action>(
Expression.Block(
new[] { var1, var2 },
Expression.Assign(
var1, Expression.New(typeof(A).GetConstructors().Single())),
Expression.Assign(
var2,
Expression.New(typeof(B).GetConstructors().Single(), var1))));
var assembly = AssemblyBuilder.DefineDynamicAssembly(
new AssemblyName("test"), AssemblyBuilderAccess.Save);
var module = assembly.DefineDynamicModule("test.dll");
var type = module.DefineType("Type");
var withBlocksMethod = type.DefineMethod(
"WithBlocks", MethodAttributes.Public | MethodAttributes.Static,
typeof(void), Type.EmptyTypes);
withBlocks.CompileToMethod(withBlocksMethod);
var withoutBlocksMethod = type.DefineMethod(
"WithoutBlocks", MethodAttributes.Public | MethodAttributes.Static,
typeof(void), Type.EmptyTypes);
withoutBlocks.CompileToMethod(withoutBlocksMethod);
type.CreateType();
assembly.Save("test.dll");
감사합니다 테스트하고 다른 사람들에게 어떻게하는지 보여줍니다. – RBJ