【问题标题】:explicit cast operator applied to instance created through reflection显式转换运算符应用于通过反射创建的实例
【发布时间】:2011-08-02 12:13:46
【问题描述】:

当我发现以下代码在运行时抛出异常时我很惊讶:

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);
    }
}

谁能告诉我为什么?我真的不明白发生了什么

【问题讨论】:

    标签: c# .net reflection casting explicit-conversion


    【解决方案1】:

    您不应该感到惊讶 - 自定义运算符不会覆盖任何东西,它们会重载 - 所以它们是在编译时选择的 ,而不是执行时间

    当我们从代码中删除隐式类型时,它会更清晰一些:

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

    现在很清楚,在最后一行中,(A) 只是来自 object 的转换,它执行正常的引用转换。根本不会应用任何用户定义的转换。

    如果您使用的是 .NET 4,则可以使用动态类型来使其工作:

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

    现在转换应用于动态值,这意味着选择使用何种转换将推迟到执行时间 - 届时它将使用您的自定义运算符。

    【讨论】:

    • 谢谢乔恩,你的帖子对我很有用!
    【解决方案2】:

    您已经创建了一个B。然后将其转换为A

    尽管布局相似,B 与 A没有关系。静态运算符由 编译器 应用,但在运行时不通过强制转换。虽然 C# 的语法是一样的,但是在处理反射的时候就大不相同了。

    这是正常的预期行为。

    【讨论】:

    【解决方案3】:

    你可以简单地改变这一行:

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

    收件人:

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

    所以编译器现在知道 bInstanceReflection 的类型并且可以调用正确的隐式运算符。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-06-23
      • 2016-09-14
      • 1970-01-01
      • 2022-01-09
      相关资源
      最近更新 更多