2014-11-12 1 views
0
C# 식 나무에서

,다른 BlockExpressions 내의 Extra BlockExpressions가 코드 생성에 영향을 줍니까?

.Block(
    ConsoleApplication2.A $var1, 
    ConsoleApplication2.B $var2) { 
    .Block() { 
     .Block() { 
      $var1 = .New ConsoleApplication2.A(); 
      $var1 
     }; 
     .Block() { 
      $var2 = .New ConsoleApplication2.B($var1); 
      $var2 
     } 
    } 
} 

위의 표현은 그들은 기능적으로 동일하지만, 첫 번째는 내가 자주 수행하여 그만 둘 것입니다

.Block(
    ConsoleApplication2.A $var1, 
    ConsoleApplication2.B $var2) { 
    $var1 = .New ConsoleApplication2.A(); 
    $var2 = .New ConsoleApplication2.B($var1); 
} 

코드 대의 품질이 좋지 생성 하는가 방문자 패턴 기반 수정.

부모 블록에 자리 표시자인 모든 블록 (즉, 변수가 없음)을 "축소"또는 "축소"할 수 있습니까? 어쩌면 또 다른 방문자를 사용하고 있을까요? 나는 그것을 이해할 수 없었다.

답변

0

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"); 
+0

감사합니다 테스트하고 다른 사람들에게 어떻게하는지 보여줍니다. – RBJ

관련 문제