Saturday, October 29, 2011

“No coercion operator is defined between types” error in expression trees

Suppose that you have 2 inherited classes:

   1: public class Bar
   2: {
   3:     public static explicit operator Bar(string s) { return null; }
   4: }
   5: public class Foo : Bar
   6: {
   7: }

As shown above in the parent class Boo there is explicit cast operator from string (the fact that it returns null is not relevant for us). With this operator you may cast Bar from string:

   1: Bar b = (Bar)"foo";

Also you may cast to Foo and compiler will allow to do that:

   1: Foo f = (Foo)"foo";

Now let’s try to construct expression tree which converts string to Foo:

   1: var expr = Expression.Convert(Expression.Constant("foo"), typeof (Foo));

It will compile but will throw exception “No coercion operator is defined between types 'System.String' and 'Foo'”. This looks strange because compiler allows to do the same cast directly.

Ok, there is overridden version of Convert method and if you checked my previous post about similar problem with LessThan method, we can try to use it in order to avoid the problem:

   1: var mi = typeof(Bar).GetMethod("op_Explicit");
   2: var expr = Expression.Convert(Expression.Constant("foo"), typeof(Foo), mi);

Unfortunately no luck here as well: it throws exception “The operands for operator 'Convert' do not match the parameters of method 'op_Explicit'”.

If you will try to get op_Explicit using Foo type:

   1: var mi = typeof (Foo).GetMethod("op_Explicit");

you will again get “No coercion operator is defined between types 'System.String' and 'Foo'”” error. The same behavior exist both in .Net 3.5 and 4.0. This problem looks like a bug in expression trees.

0 comments:

Post a Comment