Введение
Я знаю, что "пользовательские преобразования в базовый класс или из него не допускаются". MSDN дает в качестве объяснения этому правилу "Этот оператор не нужен".
Я понимаю, что пользовательское преобразование в базовый класс не требуется, поскольку это явно сделано неявно. Однако мне нужно преобразование из базового класса.
В моем текущем проекте, оболочке неуправляемого кода, я использую указатель, хранящийся в классе Entity. Все классы, использующие указатель, получают этот класс Entity, например, класс 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
...
Однако во время выполнения я получаю исключение, говорящее, что это приведение невозможно.
Заключение
Поэтому здесь я нуждаюсь в пользовательском преобразовании из базового класса, а С# отказывает мне. Используя метод 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);
}
}
Но, честно говоря, все синтаксисы для них ужасны и на самом деле должны быть отличными. Итак, любой способ заставить броски работать? Это недостаток дизайна С# или я пропустил возможность? Это как если бы С# не доверял мне достаточно, чтобы написать собственное преобразование от базового к ребенку, используя свою систему литья.