Introduccióndefinida por el usuario operador de conversión de clase base
Soy consciente de que "conversiones definidas por el usuario hacia o desde una clase base no se les permite". MSDN da, como explicación a esta regla, "No necesita este operador".
Entiendo que una conversión definida por el usuario a no es necesaria una clase base, ya que esto obviamente se hace implícitamente. Sin embargo, sí necesito una conversión de una clase base.
En mi diseño actual, un contenedor de código no administrado, uso un puntero, almacenado en una clase Entity. Todas las clases que usan un puntero derivan de esa clase Entity, por ejemplo, una clase Body.
por lo tanto tengo:
Método 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);
}
}
Este reparto es la ilegal. (Tenga en cuenta que no me molesté en escribir los accesos). Sin él, el compilador se me permite hacer:
Método B
(Body)myEntity
...
Sin embargo, en tiempo de ejecución, voy a tener una excepción diciendo que este reparto es imposible.
Conclusión
Por lo tanto, aquí estoy, que necesitan una conversión definida por el usuario de una clase base, y C# se niega a mí. Usando el método A, el compilador se quejará pero el código lógicamente funcionará en tiempo de ejecución. Usando el método B, el compilador no se quejará pero el código obviamente fallará en el tiempo de ejecución.
Lo que me parece extraño en esta situación es que MSDN me dice que no necesito este operador, y el compilador actúa como si fuera posible implícitamente (método B). ¿Que se supone que haga?
Soy consciente de que puedo usar:
Solución A
class Body : Entity
{
Body(IntPtr pointer) : base(pointer) { }
static Body FromEntity(Entity e)
{
return new Body(e.Pointer);
}
}
Solución B
class Body : Entity
{
Body(IntPtr pointer) : base(pointer) { }
Body(Entity e) : base(e.Pointer) { }
}
Solución C
class Entity
{
IntPtr Pointer;
Entity(IntPtr pointer)
{
this.Pointer = pointer;
}
Body ToBody()
{
return new Body(this.Pointer);
}
}
Pero, sinceramente, todas las sintaxis para estos son horribles y de hecho deberían ser versiones. Entonces, ¿hay alguna manera de hacer que los moldes funcionen? ¿Es un defecto de diseño de C# o perdí una posibilidad? Es como si C# no confiara lo suficiente en mí como para escribir mi propia conversión de base a hijo usando su sistema de conversión.
¿Alguien más piensa que el operador de reparto hace demasiadas cosas? Upcasting, downcasting, boxing/unboxing, conversiones definidas por el usuario ... C++ dividió su operador de reparto hace años; tal vez es hora de que C# haga lo mismo? –