6
votes

Pourquoi ne puis-je pas écrire un opérateur implicite d'une classe de base à une classe dérivée en 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

2 commentaires

Parce que la conversion existe déjà et que vous n'êtes pas autorisé à augmenter cela.


Que se passe-t-il lorsque vous souhaitez avoir une référence générale à un objet de type basoclass ? Si vous avez l'opérateur implicite de basoclass tel que défini, vous serez essentiellement "trancher" l'objet et perdant des informations d'exécution. Vous ne seriez pas en mesure de passer des appels sur des méthodes virtuelles qui ont été remplacées, le cas échéant.


5 Réponses :


9
votes

car il existe déjà une conversion implicite de dérivé à basoclass , et l'inverse n'a aucun sens.

Concernant ce dernier: si vos objets sont conçus pour être implicitement convertibles à dérivé - pourquoi ne sont-ils pas dérivé le premier endroit?

citations obligatoires du standard :

6.1.6 Conversions de référence implicites

Les conversions de référence implicites sont:

  • [...]
  • de n'importe quel type de classe S à n'importe quel type de classe T, à condition que S est dérivé de t.

    Ceci dit qu'il y a une conversion implicite dérivée => base , comme nous le savons tous.

    6.2.4 Conversions de référence explicites

    Les conversions de référence explicites sont:

    • [...]
    • de n'importe quel type de classe S à n'importe quel type de classe T, à condition que S est une classe de base de t.
    • [...]

      Ceci dit qu'il y a déjà une conversion explicite base => dérivé (ce qui vous permet d'essayer Downcasting au moment de l'exécution).

      6.4.1 Conversions définies par l'utilisateur autorisées

      C # ne permet que certaines conversions définies par l'utilisateur à déclarer. dans particulier, il n'est pas possible de redéfinir un existant déjà conversion implicite ou explicite.

      Et cela dit que, puisque les deux conversions d'intérêt sont déjà définies par la langue, vous ne pouvez pas les redéfinir.


2 commentaires

Parce qu'ils viennent de quelque part que je ne contrôle pas, par exemple.


@Stephane: Vous contrôlez le dérivé s. Alors pourquoi ne pas créer dérivé s de base S à l'avant si vous allez en avoir besoin?



1
votes

Parce que cela dérangerait les Symanitcs de polymorphisme.


0 commentaires

0
votes

Pour synthétiser, vous pouvez déjà lancer un objet dérivé dans un objet BASECLASS sans écrire de code:

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

baseClass = (BaseClass)derived;


0 commentaires

1
votes

Il existe une règle générale que le résultat de la création d'un objet à son propre type est l'objet d'origine. Si un emplacement de stockage de type BaseType contient une instance de dérivedtype , la coulée du type d'origine à dérivedtype doit indiquer au compilateur d'utiliser DeriveType S, mais ne devrait pas vraiment "faire" quoi que ce soit à l'objet. Si des opérateurs de conversion de base à base de base ont été autorisés, il serait nécessaire de: (1) avoir une opération de type propre à l'instance, donnez parfois un nouvel objet et parfois non, ni (2) ont un type dérivé. L'objet qui est stocké dans un emplacement de stockage de type base se comporte sensiblement différemment d'un objet de type de base ou de type non liée, sans code de vérification de type clairement visible qui le ferait. Bien qu'il y ait des fois on peut vouloir avoir une méthode qui, étant donné un paramètre de type de base, peut renvoyer un nouvel objet de type dérivé ou - si donné une instance du type dérivé, le retourne simplement non modifié, il est généralement préférable de avoir une telle chose "regarder" comme une méthode au lieu d'un typast.

BTW, il existe une situation dans laquelle un compilateur pourrait permettre des conversions de type définies par l'utilisateur entre un "type de base" et un "type dérivé" sans l'ambiguïté ci-dessus: lorsque l'un des types est une structure. Bien que c # prétend que les types de valeur hériter de valueltype , chaque définition de type de valeur définit vraiment deux choses: un type d'objet de tas qui dérive de valeur de valeur et une collection d'emplacements de stockage, qui n'est pas un objet et ne dérive rien. C # définit un opérateur de coulée implicite de ce dernier type à l'ancienne et un opérateur de coulée explicite du premier à celui-ci. Étant donné que la conversion entre un objet de tas et une collection d'emplacements de stockage n'est jamais une préservation de référence, permettant aux opérateurs de conversion définis par l'utilisateur à utiliser dans ce contexte ne causerait pas de sémantique de héritage confus. La seule difficulté avec une telle conversion serait le fait que les types de valeur qui les utilisaient soient inutilisables en tant que types génériques ou perdraient leur comportement spécial si elles sont transmises en tant que types génériques.


1 commentaires

Merci pour les précisions utiles.



0
votes

J'avais la nécessité de pouvoir créer un objet dérivé à partir d'un objet de base afin de capturer des informations supplémentaires que la classe de base n'avait pas. À mes besoins, la construction d'un objet dérivé avec tous les champs copiés à partir de l'objet de base était acceptable. J'ai utilisé automapper pour rendre ma vie un peu plus facile: xxx


0 commentaires