c# - 来自基类的用户定义转换运算符

标签 c# casting

简介

我知道“不允许用户定义的与基类之间的转换”。作为对此规则的解释,MSDN 给出了“您不需要此运算符”。

我明白不需要用户定义的基类的转换,因为这显然是隐式完成的。但是,我确实需要从基类进行转换。

在我当前的设计中,一个非托管代码的包装器,我使用一个指针,存储在一个实体类中。 所有使用指针的类都派生自该实体类,例如 Body 类。

因此我有:

方法A

class Entity
{
    IntPtr Pointer;

    Entity(IntPtr pointer)
    {
        this.Pointer = pointer;
    }
}

class Body : Entity
{
    Body(IntPtr pointer) : base(pointer) { }

    explicit operator Body(Entity e)
    {
        return new Body(e.Pointer);
    }
}

这个转换是非法的。 (请注意,我没有费心编写访问器)。 没有它,编译器允许我做:

方法B

(Body)myEntity
...

但是,在运行时,我会得到一个异常,说这个转换是不可能的。

结论

因此,我需要从基类 进行用户定义的转换,而 C# 拒绝了我。使用方法 A,编译器会报错,但代码在运行时逻辑上会正常工作。使用方法 B,编译器不会报错,但代码显然会在运行时失败。

在这种情况下,我觉得奇怪的是 MSDN 告诉我不需要这个运算符,编译器的行为就好像它是隐式可能的(方法 B)。我该怎么办?

我知道我可以使用:

解决方案 A

class Body : Entity
{
    Body(IntPtr pointer) : base(pointer) { }

    static Body FromEntity(Entity e)
    {
        return new Body(e.Pointer);
    }
}

方案B

class Body : Entity
{
    Body(IntPtr pointer) : base(pointer) { }

    Body(Entity e) : base(e.Pointer) { }
}

方案 C

class Entity
{
    IntPtr Pointer;

    Entity(IntPtr pointer)
    {
        this.Pointer = pointer;
    }

    Body ToBody()
    {
        return new Body(this.Pointer);
    }
}

但老实说,这些的所有语法都很糟糕,实际上应该强制转换。 那么,有什么方法可以使 Actor 阵容发挥作用吗?是 C# 设计缺陷还是我错过了一个可能性?就好像 C# 不够信任我,无法使用他们的转换系统编写我自己的基到子转换。

最佳答案

这不是设计缺陷。原因如下:

Entity entity = new Body();
Body body = (Body) entity;

如果允许您在此处编写自己的用户定义转换,将有 两个 有效转换:尝试只进行普通转换(这是一个引用转换,保留身份)和您的用户定义的转化。

应该使用哪个?您真的想要的是让它们做不同的事情吗?

// Reference conversion: preserves identity
Object entity = new Body();
Body body = (Body) entity;

// User-defined conversion: creates new instance
Entity entity = new Body();
Body body = (Body) entity;

呸!那种疯狂的谎言,IMO。不要忘记,编译器在编译时仅根据所涉及表达式的编译时类型来决定这一点。

就我个人而言,我会选择解决方案 C - 甚至可能将其设为虚拟方法。这样 Body 可以 重写它只返回 this,如果你希望它在可能的情况下保持身份但是在必要时创建一个新对象。

关于c# - 来自基类的用户定义转换运算符,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43323166/

相关文章:

c# - 无法绑定(bind)到 DataContext

c# - 适用于 WPF 的 Microsoft .NET 图表控件

c# - 根据数据 View 值在 WPF 中启用按钮

c# - 锁定集合与 syncRoot 相比有什么缺点吗?

c++ - 类型转换 std::placeholder

c# - 从左连接中选择时出现 NullReferenceException

c# - 将对象 [] 传递给参数对象 [] 不起作用

C++自动 'type cast'转换

php - MySQL 查询选择长文本数据类型的 SUM 并将结果存储为变量

c++ - 如何在不使用继承的情况下转换用户定义类的指针