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