c# formularios - lanzar objeto hijo como padre



dentro container (8)

No estás asignando el elenco a nada.

var myClass = new Child();
Parent p = (Parent)myClass;

Editar - Creo que no entiendes cómo funciona el casting. Supongamos que Parent tiene un método virtual , DoStuff() que se invalida en Child . Incluso si myClass a Parent , se ejecutará el método DoStuff del Child . No importa qué, ese Child es un Child , y siempre será un Child , incluso si lo lanzas.

Si está intentando pasarlo a un método que acepta un objeto principal, no tiene que lanzarlo. Ya es un Parent , en virtud de ser un Child .

Creo que nos estamos perdiendo algo. ¿Qué estás tratando de lograr? ¿Qué no funciona?

Necesito poder convertir una instancia de un objeto secundario a una instancia del objeto principal.

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.

¿Hay otra forma de lanzarlo?

Gracias


Acabo de encontrar una variante del problema, creo que tengo una solución no basada en serialización.

Al igual que el OP, tengo Clase B que hereda de la Clase A, y necesito B.GetType (). Nombre para regresar como si fuera la Clase A.

En la Clase B, debe anular GetType () para devolver .GetType (). BaseType

De esa manera B.GetType () siempre se verá como A.GetType ()

Como eso es bastante duro, y todas mis clases heredan de mi propia baseClass estándar, agregaré una propiedad llamada TypeName a la baseClass que devuelve esto.GetType (). Name

Luego, en mi única clase especial en la que quiero que parezca que es el padre, la anularé para devolver esto.GetType (). BaseType.Name

Luego, en mi código, haré referencia a .TypeName en lugar de hacer .GetType (). Nombre directamente cuando necesito el "enmascaramiento" especial del nombre de tipo de la clase para activarlo. Dado que solo estoy usando .GetType () en El área en la que necesito ignorar esta clase infantil es bastante limpia para mi propio uso.


Eso debería funcionar.

Pero sospecho que por la forma en que has escrito tu código, ¿no has capturado el objeto de conversión en una nueva variable? Prueba esto:

var myClass = new Child()
var myClassAsParent = (Parent)myClass;
// myClassAsParent still has the type "Child", but can be accessed as if it were a Parent.

Editar Según algunos de los comentarios que ha estado dejando, creo que malinterpreta un aspecto fundamental de la mayoría de los lenguajes de programación. Es este: el Tipo de un objeto no puede cambiar . Un objeto que se creó como un objeto secundario siempre será un objeto Child .

Casting no cambia el tipo de un objeto. El lanzamiento cambia la forma en que el resto del programa "ve" el objeto. Cambia la interfaz del objeto, si lo desea. Entonces, si lanzas un objeto Child a un tipo de Parent , el resto del programa piensa que se trata de un tipo de Parent , pero en realidad se trata de un tipo de Child , es decir, usar una analogía muy mala, vestida con la ropa de su padre.

En resumen, Casting no hace lo que crees que hace.


Tuve el mismo problema y se me ocurrió la siguiente solución:

Mi código inicial fue así:

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 Employee() : base();
}

y cuando intenté lanzar un objeto Person a un cliente, recibí errores de "error de lanzamiento"

En lugar de seguir con la idea de lanzar, decidí modificar los constructores de copias del Niño, por lo tanto:

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);
}

El problema es que el serializador xml serializa el objeto con tipo secundario como elemento raíz. Realmente no quiero pasar mi tipo de destino hasta el serializador. ¿hay una mejor manera? - Jules

No he trabajado mucho con la serialización, pero supongo que necesitarás modificar tu definición de "cómo me serializo" en el elemento hijo para escribir como si fuera un padre.

Si realmente desea tener una instancia de "Padre", deberá crear un nuevo Padre y copiar todos los valores del Niño al Padre. (No haría esto si tiene muchos de ellos, pero si no tiene tantos, no debería ser un problema). La forma más sencilla de hacerlo sería crear un constructor de copias en Padre. Sería un constructor que toma un padre como parámetro y copia los valores (nombre en este caso, y supongo que puede haber omitido otros) del parámetro a sí mismo. Luego, puede crear un nuevo Padre, pasar el Niño como parámetro (ya que un Niño es un Padre, no se necesita conversión / conversión) y escupirá una instancia real del Padre.


Si Parent es una superclase de Child , entonces automáticamente un Child es también Parent (contiene todas las propiedades y métodos de `Parent) y no es necesario realizar la conversión.

Además, no puedes simplemente comenzar una línea con un lanzamiento. Podrías escribir por ejemplo

Parent p = (Parent)myClass;

podría usar el operador como ... lo bueno de ESO es que no se lanzará ninguna excepción y puede verificar si el "lanzamiento" falla.

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");

A veces utilizo un enfoque que se asemeja a las respuestas que utilizan la inyección de propiedades, pero mantiene el código más limpio. En lugar de tener una clase / interfaz base con un conjunto de propiedades, solo contiene un método Initialize (virtual) (virtual) que actúa como un "constructor de hombres pobres". Luego, puede dejar que cada clase maneje su propia inicialización como lo haría un constructor, lo que también agrega una forma conveniente de manejar las cadenas de herencia.

Si a menudo me encuentro en situaciones en las que quiero que cada clase en la cadena inicialice sus propiedades únicas, y luego llame a su método principal, Initialize (), que a su vez inicializa las propiedades únicas de los padres, etc. Esto es especialmente útil cuando se tienen diferentes clases, pero con una jerarquía similar, por ejemplo, los objetos comerciales que se asignan a / desde DTO: s.

Ejemplo que usa un diccionario común para la inicialización:

void Main()
{
    var values = new Dictionary<string, int> { { "BaseValue", 1 }, { "DerivedValue", 2 } };

    Console.WriteLine(CreateObject<Base>(values).ToString());

    Console.WriteLine(CreateObject<Derived>(values).ToString());
}

public T CreateObject<T>(IDictionary<string, int> values)
    where T : Base, new()
{
    var obj = new T();
    obj.Initialize(values);
    return obj;
}

public class Base
{
    public int BaseValue { get; set; }

    public virtual void Initialize(IDictionary<string, int> values)
    {
        BaseValue = values["BaseValue"];
    }

    public override string ToString()
    {
        return "BaseValue = " + BaseValue;
    }
}

public class Derived : Base
{
    public int DerivedValue { get; set; }

    public override void Initialize(IDictionary<string, int> values)
    {
        base.Initialize(values);
        DerivedValue = values["DerivedValue"];
    }

    public override string ToString()
    {       
        return base.ToString() + ", DerivedValue = " + DerivedValue;
    }
}



c#  

c#