简体   繁体   English

为什么我不能将一个隐式运算符从Base类写入C#中的Derived类?

[英]Why can't I write an implicit operator from a Base class to a Derived class in C#?

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

This won't work. 这不行。 why isn't it allowed? 为什么不允许?
I can potentially write the logic necessary for it to make sense, especially when converting from the base to the derived one. 可以写出有必要的逻辑,特别是在从基础转换为派生的逻辑时。

EDIT:Changed the title of the question 编辑:更改了问题的标题

Because there is already an implicit conversion from Derived to BaseClass , and the converse does not make any sense. 因为已经有从DerivedBaseClass的隐式转换,并且反过来没有任何意义。

Regarding the latter: if your Base objects are meant to be implicitly convertible to Derived -- why aren't they Derived objects in the first place? 关于后者:如果您的Base对象可以隐式转换为Derived - 为什么它们不是Derived对象?

Obligatory quotes from the standard : 标准的强制性引用:

6.1.6 Implicit reference conversions 6.1.6隐式引用转换

The implicit reference conversions are: 隐式引用转换是:

  • [...] [...]
  • From any class-type S to any class-type T, provided S is derived from T. 从任何类型S到任何类型类型T,只要S来自T.

This says there's an implicit conversion Derived => Base , as we all know. 这表示存在一个隐式转换Derived => Base ,我们都知道。

6.2.4 Explicit reference conversions 6.2.4显式引用转换

The explicit reference conversions are: 显式引用转换是:

  • [...] [...]
  • From any class-type S to any class-type T, provided S is a base class of T. 从任何类型S到任何类型类型T,只要S是T的基类。
  • [...] [...]

This says there's already an explicit conversion Base => Derived (which is what allows you to try downcasting at runtime). 这表示已经有一个显式转换Base => Derived (这是允许你在运行时尝试向下转换的原因)。

6.4.1 Permitted user-defined conversions 6.4.1允许的用户定义转换

C# permits only certain user-defined conversions to be declared. C#仅允许声明某些用户定义的转换。 In particular, it is not possible to redefine an already existing implicit or explicit conversion. 特别是,无法重新定义已存在的隐式或显式转换。

And this says that since the two conversions of interest are already defined by the language, you can't redefine them. 这说明由于两种兴趣转换已经由语言定义,因此您无法重新定义它们。

因为它会扰乱多态性的系统。

There is a general rule that the result of casting an object to its own type is the original object. 通常的规则是将对象转换为自己的类型的结果是原始对象。 If a storage location of type BaseType holds an instance of DerivedType , casting from the original type to DerivedType should tell the compiler to use DerivedType 's members, but shouldn't actually "do" anything to the object. 如果BaseType类型的存储位置包含DerivedType的实例, DerivedType原始类型转换为DerivedType应该告诉编译器使用DerivedType的成员,但实际上不应该对该对象“执行”任何操作。 If custom base-to-derived conversion operators were allowed, it would be necessary to either: (1) Have a cast-to-instance's own-type operation sometimes yield a new object and sometimes not, or (2) Have a derived type object which is stored in a base-type storage location behave substantially differently from a base-type or unrelated-type object, without clearly visible type-checking code that would make it do so. 如果允许自定义的从基础到派生的转换运算符,则有必要:(1)具有转换为实例的自有类型操作有时会产生新对象,有时不产生,或者(2)具有派生类型存储在基本类型存储位置中的对象与基本类型或不相关类型的对象的行为基本不同,没有明确可见的类型检查代码,这将使其这样做。 While there are times one might want to have a method which, given a base-type parameter, might return a new derived-type object or--if given an instance of the derived type, simply return it unmodified, it is generally better to have such a thing "look" like a method instead of a typecast. 虽然有时候人们可能想要一个方法,给定一个base-type参数,可能会返回一个新的派生类型对象,或者 - 如果给定一个派生类型的实例,只需返回它未经修改,通常更好的方法是有这样的东西“看起来”像一个方法而不是类型转换。

BTW, there is one situation where a compiler could allow user-defined type conversions between a "base type" and a "derived type" without the above ambiguity: when one of the types is a struct. 顺便说一句,有一种情况是编译器可以在“基本类型”和“派生类型”之间允许用户定义的类型转换而没有上述歧义:当其中一个类型是结构时。 Although C# pretends that value types inherit from ValueType , every value type definition really defines two things: a heap object type which derives from ValueType , and a collection of storage locations, which isn't an object and doesn't derive from anything. 虽然C#假装值类型继承自ValueType ,但每个值类型定义实际上定义了两件事:一个派生自ValueType的堆对象类型,以及一个存储位置集合,它不是一个对象,也不是从任何东西派生的。 C# defines an implicit casting operator from the latter type to the former, and an explicit casting operator from the former to the latter. C#定义了从后一种类型到前者的隐式转换运算符,以及从前者到后者的显式转换运算符。 Since conversion between a heap object and a collection of storage locations is never reference preserving, allowing user-defined conversion operators to be used in such context would not cause muddled inheritance semantics. 由于堆对象和存储位置集合之间的转换永远不会引用保留,因此允许在此类上下文中使用用户定义的转换运算符不会导致混乱的继承语义。 The only difficulty with such conversion would be the fact that value types which used them would either be unusable as generic types, or would lose their special behavior if passed as generic types. 这种转换的唯一困难是使用它们的值类型要么作为泛型类型不可用,要么如果作为泛型类型传递则会丢失它们的特殊行为。

To synthesize you can already cast a Derived object into a BaseClass object without writing any code : 要合成,您可以将Derived对象转换为BaseClass对象,而无需编写任何代码:

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

baseClass = (BaseClass)derived;

But you can't rewrite the cast from Derived to BaseClass. 但是你无法将Derived重写为BaseClass。

For the other cast, from BaseClass to Derived, it doesn't make so much sense. 对于其他演员,从BaseClass到Derived,它没那么有意义。

In conclusion you can redefine the cast only if there is no inheritance relation between the 2 classes. 总之,只有在两个类之间没有继承关系时,才能重新定义强制转换。

I had the need to be able to create a derived object from a base object in order to capture additional information that the base class did not have. 我需要能够从基础对象创建派生对象,以捕获基类没有的其他信息。 For my purposes, construction a derived object with all the fields copied from the base object was acceptable. 出于我的目的,构造一个派生对象,其中包含从基础对象复制的所有字段。 I used AutoMapper to make my life a bit easier: 我使用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>();
    }
};

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何编写一个函数来返回从C#中的基类派生的任何对象? - How can I write a function that returns any object derived from a base class in C#? C#可以从派生类调用基类属性吗 - C# Can a base class property be invoked from derived class 无法访问派生类(C#)中的基本属性 - Can't access base properties in derived class (C#) C#:如何从派生类设置属性的最大值? (而不是在基类中) - C#: How can I set a maximal Value of a property from a derived class? (And not in base class) 为什么事件不能在派生类中以与C#中的基类相同的方式使用? - Why events can't be used in the same way in derived classes as in the base class in C#? c#从基类隐式转换 - c# implicit conversion from base class 您能否将派生类添加到其基类列表中,然后从C#中的基类列表中调用派生类的方法 - Can you add a Derived Class to a list of its base class then call a method of the Derived class from the list of base class in C# 我无法从基础 class c# 访问变量 - I can't access variable from base class c# 在C#oop中如何解释为什么基类可以采用派生类实例 - in c# oop how to explain why a base class can take a derived class instance C#将相同的属性从派生类克隆到基类 - C# Clone same properties from Derived class to base class
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM