Лить дочерний объект как родителя
Мне нужно уметь экземпляр дочернего объекта экземпляру родительского объекта.
public class Parent
{
public string name{get;set;}
}
public class Child : Parent{}
var myClass = new Child()
(Parent)myClass
//this doesnt seem to work and the object still has childs type.
есть ли другой способ сделать это?
спасибо
Ответы
Ответ 1
Проблема - сериализатор xml сериализует объект с типом child как корневой элемент. Я действительно не хочу передавать свой целевой тип полностью вниз в сериализатор. Есть ли способ лучше? - Жюль
Я много не работал с сериализацией, но думаю, вам придется изменить свое определение "как я сериализую себя" в дочернем элементе, чтобы написать себя, как если бы это был родитель.
Если вы действительно хотите иметь экземпляр "Родитель", вам нужно создать нового родителя и скопировать все значения из Ребенка в этот родитель. (Я бы не сделал этого, если у вас их много, но если у вас их нет, это не должно быть проблемой.) Самый простой способ сделать это - создать конструктор копирования в Parent. Это был бы конструктор, который принимает Parent как параметр и копирует значения (Name в этом случае, и я предполагаю, что вы, возможно, опустили другие), от параметра к себе. Затем вы можете создать нового родителя, передать его в качестве параметра (поскольку ребенок является родителем, не требуется преобразование/преобразование), и он выплюнет фактический экземпляр родителя.
Ответ 2
Вы не назначаете приведение к чему-либо.
var myClass = new Child();
Parent p = (Parent)myClass;
Изменить. Я думаю, вы неправильно поняли, как работает кастинг. У Say Parent есть метод virtual
, DoStuff()
. который переопределяется в Child
. Даже если вы отбрасываете myClass
в Parent
, он запускает метод Child
DoStuff
. Независимо от того, что Child
является Child
и всегда будет Child
, даже если вы его произнесли.
Если вы пытаетесь передать его методу, который принимает объект Parent
, вам не нужно его использовать. Он уже a Parent
, благодаря a Child
.
Я думаю, что мы чего-то не замечаем. Что вы пытаетесь совершить? Что не работает?
Ответ 3
Это должно работать.
Но я подозреваю, что вы написали свой код, что вы не захватили объект cast в новой переменной? Попробуйте следующее:
var myClass = new Child()
var myClassAsParent = (Parent)myClass;
// myClassAsParent still has the type "Child", but can be accessed as if it were a Parent.
Edit
Основываясь на некоторых комментариях, которые вы оставили, я считаю, что вы неправильно понимаете фундаментальный аспект большинства языков программирования. Это так: Тип объекта не может измениться. Объект, который был создан как объект Child
, всегда будет объектом Child
.
Кастинг не меняет тип объекта. Кастинг изменяет способ, которым остальная часть программы "видит" объект. Он изменяет интерфейс объекта, если хотите. Поэтому, если вы добавили объект Child
к типу Parent
, остальная часть программы считает, что он имеет дело с типом Parent
, но он действительно имеет дело с типом Child
, который заключается в использовании действительно плохой аналогии, одетый в свою родительскую одежду.
Короче говоря, Кастинг не делает того, что вы думаете.
Ответ 4
вы можете использовать оператор as... хорошая вещь о THAT не является исключением, и вы можете проверить значение null, если "cast" терпит неудачу.
public class Parent
{
public string name{get;set;}
}
public class child : Parent{}
var myClass = new Child()
Parent foo = myClass as Parent
if ( foo == null ) Debug.WriteLine("foo is NOT of type Parent");
Ответ 5
Если Parent
является суперклассом Child
, тогда автоматически a Child
также является Parent
(содержит все свойства и методы "Parent" ), и вам не нужно делать бросок.
Кроме того, вы не можете просто запустить строку с литой. Например, вы можете написать
Parent p = (Parent)myClass;
Ответ 6
Просто ударив вариант проблемы, я думаю, что у меня есть решение, не основанное на сериализации.
Как и у OP, у меня есть класс B, который наследуется от класса A, и мне нужно B.GetType(). Имя для возврата, как если бы это был класс A.
В классе B вам нужно переопределить GetType() для возврата .GetType(). BaseType
Таким образом, B.GetType() всегда будет выглядеть как A.GetType()
Как это довольно тяжело, и все мои классы наследуют от моего собственного стандартного baseClass, я собираюсь добавить свойство, называемое TypeName, в baseClass, которое возвращает this.GetType(). Name
Затем на моем одном специальном классе, который должен выглядеть как родительский, я переопределю его, чтобы вернуть this.GetType(). BaseType.Name
Затем в моем коде я буду ссылаться на .TypeName вместо того, чтобы делать .GetType(). Имя непосредственно, когда мне нужно специальное "маскирование" имени типа класса, которое нужно использовать. Учитывая, что я использую только .GetType() в той области, где мне нужно игнорировать этот дочерний класс, он достаточно чист для моего собственного использования.
Ответ 7
У меня была та же проблема и вышло следующее решение:
Мой исходный код был таким образом:
public class Person
{
public string Name { get; set; }
public Person() {};
public Person( Person rhs )
{
Name = rhs.Name;
}
}
public class Customer : Person
{
private string m_role = "Customer";
public string Role { get m_role; }
public Customer() : base();
}
public class Employee : Person
{
private string m_role = "Employee";
public string Role { get m_role; }
public Customer() : base();
}
и когда я попробовал лить объект Person клиенту, я получил ошибки "сбой"
Вместо того, чтобы преследовать идею кастинга, я решил изменить конструкторы Child copy, таким образом:
public class Customer : Person
{
private string m_role = "Customer";
public string Role { get m_role; }
public Customer() : base();
public Customer( Person per ) : base( per);
}
public class Employee : Person
{
private string m_role = "Employee";
public string Role { get m_role; }
public Employee () : base();
public Employee ( Person per) : base( per);
}
Ответ 8
Мне около пяти лет здесь, но...
Вы можете использовать AutoMapper, чтобы решить вашу проблему.
Просто определите сопоставление между родительским и дочерним классами. Простейшая карта будет делать. В классе, где вы определяете свои сопоставления:
CreateMap<Child, Parent>();
Затем в любой точке вашего кода вы можете сделать:
Child child = new Child();
Parent parent = Mapper.Map<Parent>(child);
И ваш объект parent
будет чистым parent
без каких-либо свойств объекта child
.
Как говорили другие, бросание объекта будет сохранять его тип. Это только изменяет указатель. Но AutoMapper создает новый экземпляр целевого типа и копирует значения из этого параметра в экземпляр целевого типа, сопоставляя свойства по имени.