Skip to content

Instantly share code, notes, and snippets.

@AlbertoMonteiro
Created August 8, 2012 21:11
Show Gist options
  • Save AlbertoMonteiro/3298815 to your computer and use it in GitHub Desktop.
Save AlbertoMonteiro/3298815 to your computer and use it in GitHub Desktop.
Division with IL and Expression Tree
using System;
using System.Linq.Expressions;
using System.Reflection.Emit;
namespace ConsoleApplication11
{
class Program
{
static void Main(string[] args)
{
var divisor = CriaDivisor();
var criaDivisorIL = CriaDivisorIL();
Console.WriteLine("Usando Expression");
Console.WriteLine("4 ÷ 2 = {0}", divisor(4, 2));
Console.WriteLine("4 ÷ 0 = {0}", divisor(4, 0));
Console.WriteLine("4 ÷ 4 = {0}", divisor(4, 4));
Console.WriteLine("Usando IL puro");
Console.WriteLine("2 ÷ 1 = {0}", criaDivisorIL(2, 1));
}
static Func<double, double, double> CriaDivisor()
{
var type = typeof(double);
var valor1 = Expression.Parameter(type, "valor1");
var valor2 = Expression.Parameter(type, "valor2");
var resultado = Expression.Variable(type, "resultado");
var zero = Expression.Constant(0d);
var valor2DiferenteDe0 = Expression.NotEqual(valor2, zero);
var divisao = Expression.Divide(valor1, valor2);
var ifTrue = Expression.Assign(resultado, divisao);
var ifFalse = Expression.Assign(resultado, zero);
var ifThenElse = Expression.IfThenElse(valor2DiferenteDe0, ifTrue, ifFalse);
var blockExpression = Expression.Block(new[] { resultado }, ifThenElse, resultado);
var lambda = Expression.Lambda<Func<double, double, double>>(blockExpression, new[] { valor1, valor2 });
return lambda.Compile();
}
static Func<double, double, double> CriaDivisorIL()
{
var type = typeof(double);
var divisorIL = new DynamicMethod("DivisorIL", type, new[] {type, type});
var il = divisorIL.GetILGenerator();
var ret = il.DefineLabel();
var load0 = il.DefineLabel();
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Ldc_R8,0d);
il.Emit(OpCodes.Beq, load0);
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Div);
il.Emit(OpCodes.Br, ret);
il.MarkLabel(load0);
il.Emit(OpCodes.Ldc_R8, 0d);
il.MarkLabel(ret);
il.Emit(OpCodes.Ret);
return (Func<double, double, double>)divisorIL.CreateDelegate(typeof(Func<double, double, double>));
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment