tags:

views:

72

answers:

1

The following code throws an exception. TryConvert is not being called for the cast to interface. Why is this? Can I work around the problem?

using System.Dynamic;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            dynamic test = new JsonNull();
            var ok = (string)test;
            // Next line throws:
            // Unable to cast object of type 'ConsoleApplication1.JsonNull' to type 'ConsoleApplication1.IFoo'.
            var fail = (IFoo)test;
        }
    }

    class JsonNull : DynamicObject
    {
        public override bool TryConvert(ConvertBinder binder, out object result)
        {
            result = null;
            return !binder.Type.IsValueType;
        }
    }

    interface IFoo { }
}
+1  A: 

I suspect it's because in C# (and possibly .NET in general) you can't create a user-defined conversion to an interface type (in the same way that you can't create a user-defined conversion to/from a base/child type). Every interface conversion is therefore treated as a box or a reference conversion.

That really is just a guess though.

EDIT: On the other hand, I've just had a look at the code generated for:

dynamic d = ...;
IDisposable x = (IDisposable) d;

and it does generate a dynamic call via Binder.Convert, so it's not the C# compiler doing this. Hmm.

Jon Skeet
That was my hunch too. I assume casting to an interface is not meant to return a different object instance, just a different view of the same instance.
Andrew Davey
@Andrew: You might want to *try* implementing `IDynamicMetaObjectProvider` yourself. I wonder whether it gets that far.
Jon Skeet