Reputation: 19966
Consider the MyDecimal
class below. In C#
we can cast it to an integer thanks to the implicit decimal
operator:
int i = (int)new MyDecimal(123m);
How do you produce the equivalent code in an expression tree?
When using Expression.Convert (.NET 4.5.1
) it immediately fails with No coercion operator is defined between types 'System.Int32' and 'MyDecimal'
. It seems to only consider implicit cast operators.
try
{
var param = Expression.Parameter(typeof(int), null);
var convert = Expression.Convert(param, typeof(MyDecimal));
}
catch (Exception ex)
{
}
MyDecimal
class:
public class MyDecimal
{
private readonly decimal value;
public MyDecimal(decimal value)
{
this.value = value;
}
public static implicit operator decimal(MyDecimal myDecimal)
{
return myDecimal.value;
}
public static implicit operator MyDecimal(decimal value)
{
return new MyDecimal(value);
}
}
Upvotes: 4
Views: 1520
Reputation: 7846
It's always interesting to example the expression tree of an Expression Lambda that does the same thing:
Expression<Func<MyDecimal,int>> convert = m => (int)m;
Using a tool link LinqPad we can examine convert and see we have the following:
Expression<Func<MyDecimal,int>> (type: Lambda)
|
+- UnaryExpression (type:Convert) - Convert(int, decimal)
|
+- UnaryExpression (type:Convert) - Convert(decmal, MyDecimal)
So, although the compiler allows the implicit conversion from decimal
to int
, you can see that the equivalent Lambda
requires the conversion to be explicit.
EDIT
So, to construct the complete expression, you've have something like:
Expression.Assign(
Expression.Variable(typeof(int), "i"),
Expression.Convert(
Expression.Convert(
Expression.New(
typeof(MyDecimal).GetConstructor(new[] {typeof(decimal)}),
Expression.Convert(
Expression.Constant(1),
typeof(decimal)
)
),
typeof(decimal)),
typeof(int)
)
)
Some points to note:
int
1 to decimal
to pass to the constructori
is already declared.Upvotes: 4