call site and type conversion

Apr 11, 2010 at 11:53 AM

 

InvalidCastException
{"The result type 'System.Int32' of the dynamic binding produced by the object with type 'MopExamples.Customer' for the binder 'Microsoft.CSharp.RuntimeBinder.CSharpSetMemberBinder' is not compatible with the result type 'System.Object' expected by the calHi,

I implemented the BindSetMember like this:

public override DynamicMetaObject BindSetMember(SetMemberBinder binder, DynamicMetaObject value)
{
     Console.WriteLine("Setting member {0}", binder.Name);

     Expression setMemberExpression =
          Expression.Assign(
               Expression.Property(
                     Expression.Constant(this.Value), binder.Name),
               Expression.Constant(6));

     return new DynamicMetaObject(setMemberExpression, 
            restrictions);
 }

When I run the code, I get an InvalidCastException that says:

{"The result type 'System.Int32' of the dynamic binding produced by the object with type 'MopExamples.Customer' for the binder 'Microsoft.CSharp.RuntimeBinder.CSharpSetMemberBinder' is not compatible with the result type 'System.Object' expected by the call site."}

My BindSetMember implementation basically returns to the call site an expression that assigns number 6 to a property. It seems that the call site expects the type of that assignment to be object while the type of the expression I return is Int32. If I call Expression.Convert(setMemberExpression, typeof(object)), that will make the call site happy. However, my question is (a) why the call site expects the type of the property setting statement to be object? (b) why the conversion from Int32 to object doesn't happen automatically? (c) why the call site doesn't ignore that type since a property setting statement does not have a result type?

 

 

 

 

Apr 12, 2010 at 2:42 AM

(c) But of course a property setter has a result type and value! Otherwise, you couldn't say "a.Foo = b.Foo = 1;"! There, the value of a.Foo is set to the result of evaluating "b.Foo = 1". Evaluating "b.Foo = 1" -- when statically typed -- has the side effect of setting the property Foo on b equal to one, and then returns the value one. The same is true when runtime binding is involved. The DLR/LINQ expression trees make this pretty easy because nearly every expression has a resulting value and type. In fact, you sometimes need to throw the value away by saying "Expression.Block(some_other_expression, Expression.Empty())".

(a) C# defines most operations on a "dynamic" object to have a dynamic result type. At runtime, "dynamic" is represented as "object" so just about every C# call site has a result type of "object".

(b) Automatic conversions hide bugs in user code.