开发者

explicit cast operator applied to instance created through reflection

开发者_开发技巧

I was suprised when found that the following code throws exception at runtime:

class A
{
    public string Name { get; set; }

    public A()
    {
        Name = "Class A";
    }
}

class B
{
    public string Name { get; set; }

    public B()
    {
        Name = "Class B";
    }

    public static explicit operator A(B source)
    {
        return new A() {Name = source.Name};
    }
}


class Program
{
    static void Main(string[] args)
    {
        // This executes with no error
        var bInstance = new B();
        Console.WriteLine(bInstance.GetType()); // <assemblyname>.B
        var aInstance = (A) bInstance;
        Console.WriteLine(aInstance.Name); // Class B

        // This fails with InvalidCastException
        var bInstanceReflection = Activator.CreateInstance(typeof (B));
        Console.WriteLine(bInstanceReflection.GetType()); // <assemblyname>.B
        var aInstanceReflection = (A) bInstanceReflection;

        Console.WriteLine(aInstanceReflection.Name);
    }
}

Could anyone tell me why? I don't really understand what happened


You shouldn't be surprised - custom operators don't override anything, they overload - so they're picked at compile time, not execution time.

When we remove implicit typing from the code, it makes it a bit clearer:

object bInstanceReflection = Activator.CreateInstance(typeof (B));
Console.WriteLine(bInstanceReflection.GetType()); // <assemblyname>.B
A aInstanceReflection = (A) bInstanceReflection;

Now it's reasonably clear that in the final line, (A) is just a cast from object which performs the normal reference conversion. No user-defined conversions will be applied at all.

If you're using .NET 4, you can use dynamic typing to get it to work:

// Note the change of type
dynamic bInstanceReflection = Activator.CreateInstance(typeof (B));
Console.WriteLine(bInstanceReflection.GetType()); // <assemblyname>.B
A aInstanceReflection = (A) bInstanceReflection;

Now the conversion is being applied on a dynamic value, which means the choice of what conversion to use is deferred until execution time - at which point it will use your custom operator.


You've created a B. And then cast it to an A.

Despite having similar layouts, B has no relationship to A. Static operators are applied by the compiler, but not at runtime via cast. Although the C# syntax is the same, they are very different when dealing with reflection.

This is the normal, expected behaviour.


You can simply change this line:

var bInstanceReflection = Activator.CreateInstance(typeof (B));

To:

var bInstanceReflection = (B)Activator.CreateInstance(typeof (B));

So the compiler now knows the type of bInstanceReflection and can call the correct implitic operator.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜