6
public class Derived : BaseClass
{
    public Derived(string name) : base(name) {}

    public static implicit operator BaseClass(Derived derived)
    {
        return new BaseClass(derived.ColorHex);
    }

    public static implicit operator Derived(BaseClass baseclass)
    {
        return new Derived(baseclass.name);
    }
}

这行不通。为什么不允许?
可能会编写必要的逻辑以使其有意义,尤其是在从基础转换为派生逻辑时。

编辑:更改了问题的标题

4

5 回答 5

9

因为已经存在从Derivedto的隐式转换BaseClass,反之则没有任何意义。

关于后者:如果您的Base对象旨在隐式转换为Derived- 为什么它们Derived首先不是对象?

标准中的强制性报价:

6.1.6 隐式引用转换

隐式引用转换是:

  • [...]
  • 从任何类类型 S 到任何类类型 T,只要 S 派生自 T。

众所周知,这表示存在隐式转换Derived=> 。Base

6.2.4 显式引用转换

显式参考转换是:

  • [...]
  • 从任何类类型 S 到任何类类型 T,只要 S 是 T 的基类。
  • [...]

这表示已经有一个显式转换Base=> Derived(这允许您在运行时尝试向下转换)。

6.4.1 允许的用户定义转换

C# 只允许声明某些用户定义的转换。特别是,不可能重新定义已经存在的隐式或显式转换。

这就是说,由于语言已经定义了两个感兴趣的转换,因此您无法重新定义它们。

于 2012-06-01T15:29:14.293 回答
1

因为它会扰乱多态性的语义。

于 2012-06-01T15:29:43.763 回答
1

有一个一般规则,将对象转换为自己的类型的结果是原始对象。如果类型的存储位置BaseType包含 的实例DerivedType,则从原始类型转换为DerivedType应该告诉编译器使用DerivedType的成员,但实际上不应该对对象“做”任何事情。如果允许自定义基到派生的转换运算符,则有必要:(1)有一个转换为实例的自身类型操作有时会产生一个新对象,有时不会,或者(2)有一个派生类型存储在基本类型存储位置的对象的行为与基本类型或不相关类型的对象大不相同,没有清晰可见的类型检查代码可以做到这一点。虽然有时人们可能想要一个方法,给定一个基类型参数,它可能会返回一个新的派生类型对象,或者——如果给定派生类型的一个实例,只需不加修改地返回它,通常最好有这样一个“看起来”像方法而不是类型转换的东西。

顺便说一句,在一种情况下,编译器可以允许在“基本类型”和“派生类型”之间进行用户定义的类型转换,而不会出现上述歧义:当其中一种类型是结构时。尽管 C# 假装值类型继承自ValueType,但每个值类型定义实际上都定义了两件事:一个派生自ValueType,以及存储位置的集合,它不是一个对象,也不是从任何东西派生的。C# 定义了从后者类型到前者的隐式转换运算符,以及从前者到后者的显式转换运算符。由于堆对象和存储位置集合之间的转换永远不会保留引用,因此允许在这种上下文中使用用户定义的转换运算符不会导致继承语义混乱。这种转换的唯一困难是使用它们的值类型要么不能作为泛型类型使用,要么如果作为泛型类型传递将失去它们的特殊行为。

于 2012-06-01T17:38:34.367 回答
0

要进行综合,您已经可以将 Derived 对象转换为 BaseClass 对象,而无需编写任何代码:

BaseClass baseClass = new BaseClass("");
Derived derived = new Derived("");

baseClass = (BaseClass)derived;

但是您不能将转换从 Derived 重写为 BaseClass。

对于其他演员,从 BaseClass 到 Derived,它没有多大意义。

总之,只有当 2 个类之间没有继承关系时,您才能重新定义强制转换。

于 2012-06-01T15:39:09.973 回答
0

我需要能够从基对象创建派生对象,以便捕获基类没有的附加信息。出于我的目的,构造一个包含从基础对象复制的所有字段的派生对象是可以接受的。我使用 AutoMapper 让我的生活更轻松:

class AnnotatedAlert : Alert
{
    public string Color;

    // I don't know why C# doesn't allow user defined conversions from a base class
    // so I am creating a conversion constructor instead
    public AnnotatedAlert(Alert from)
    {
        AutoMapper.Mapper.Map(from, this);
    }

    static AnnotatedAlert()
    {
        AutoMapper.Mapper.CreateMap<Alert, AnnotatedAlert>();
    }
};
于 2017-07-20T19:38:45.707 回答