2012-09-24 45 views
72

¿Es posible en C# convertir explícitamente un objeto de clase base a una de sus clases derivadas? Actualmente estoy pensando en crear un constructor para mis clases derivadas que acepten un objeto de clase base como parámetro y copien los valores de las propiedades. Realmente no me gusta esta idea, así que me gustaría evitarla si es posible.Convertir clase base a clase derivada

esto no parece que debería funcionar (objeto se instancia como nueva base, por lo que la memoria no debería asignarse para ser miembros adicionales de la clase derivada) pero C# parece permitir que lo haga:

class BaseClass 
{ 
    ... some stuff ... 
} 

class DerivedClass : BaseClass 
{ 
    public bool MyDerivedProperty{ get; set; } 
} 


static void Main(string[] args) 
{ 
    BaseClass myBaseObject = new BaseClass(); 
    DerivedClass myDerivedObject = myBaseObject as DerivedClass; 

    myDerivedObject.MyDerivedProperty = true; 
} 
+4

Usted va a obtener una excepción de referencia nula en la última línea. – Erix

+0

Ya se ha respondido aquí: http://stackoverflow.com/questions/729527/is-it-possible-to-assign-a-base-class-object-to-a-derived-class-reference-with-a –

+1

Usted debería leer sobre cuándo es apropiado usar "como" frente a un reparto regular. Si utilizas un elenco aquí, el compilador de C# te dirá que lo que estás haciendo está mal. –

Respuesta

57

No, no hay una forma incorporada de convertir una clase como usted dice. La forma más sencilla de hacer esto sería hacer lo que sugirió: crear un constructor DerivedClass(BaseClass). En general, vendrían otras opciones para automatizar la copia de propiedades desde la base hasta la instancia derivada, p. usando la reflexión

El código que envió usando as compilará, como estoy seguro que has visto, pero voy a lanzar una excepción de referencia nula cuando se ejecuta, porque myBaseObject as DerivedClass evaluará a null, ya que no es una instancia de DerivedClass.

1

No, no hay una conversión incorporada para esto. Tendrá que crear un constructor, como usted mencionó, o algún otro método de conversión.

Además, dado que BaseClass no es un DerivedClass, myDerivedObject será nulo, yd la última línea anterior emitirá una excepción de ref nula.

3

No, no es posible. La única forma posible es

static void Main(string[] args) 
{ 
    BaseClass myBaseObject = new DerivedClass(); 
    DerivedClass myDerivedObject = myBaseObject as DerivedClass; 

    myDerivedObject.MyDerivedProperty = true; 
} 
+5

, esto arroja una NullReferenceException, por lo que no funciona como se indica –

+0

gracias por esto, las otras respuestas no dicen cómo emitir –

+0

A veces, un poco de repensando, puede salvar de problemas mayores. ¡Gracias! – peter70

5

Puede implementar la conversión usted mismo, pero yo no lo recomendaría. Eche un vistazo a Decorator Pattern si desea hacer esto para extender la funcionalidad de un objeto existente.

33

Eso no es posible. pero se puede utilizar un asignador de objetos como AutoMapper

Ejemplo:

class A 
{ 
    public int IntProp { get; set; } 
} 
class B 
{ 
    public int IntProp { get; set; } 
    public string StrProp { get; set; } 
} 

En Global.asax o inicio de la aplicación:

AutoMapper.Mapper.CreateMap<A, B>(); 

Uso:

var b = AutoMapper.Mapper.Map<B>(a); 

Es fácilmente configurable a través una API fluida

7

He encontrado una solución para esto, sin decir que sea la mejor, pero se siente limpia para mí y no requiere ningún cambio importante en mi código. Mi código se parecía al tuyo hasta que me di cuenta de que no funcionaba.Clase

mi base

public class MyBaseClass 
{ 
    public string BaseProperty1 { get; set; } 
    public string BaseProperty2 { get; set; } 
    public string BaseProperty3 { get; set; } 
    public string BaseProperty4 { get; set; } 
    public string BaseProperty5 { get; set; } 
} 

Mi clase derivada

public class MyDerivedClass : MyBaseClass 
{ 
    public string DerivedProperty1 { get; set; } 
    public string DerivedProperty2 { get; set; } 
    public string DerivedProperty3 { get; set; } 
} 

método anterior para obtener una clase base poblada

public MyBaseClass GetPopulatedBaseClass() 
{ 
    var myBaseClass = new MyBaseClass(); 

    myBaseClass.BaseProperty1 = "Something" 
    myBaseClass.BaseProperty2 = "Something else" 
    myBaseClass.BaseProperty3 = "Something more" 
    //etc... 

    return myBaseClass; 
} 

Antes de que yo estaba tratando de esto, lo que me dio un incapaz de lanzar error

public MyDerivedClass GetPopulatedDerivedClass() 
{ 
    var newDerivedClass = (MyDerivedClass)GetPopulatedBaseClass(); 

    newDerivedClass.UniqueProperty1 = "Some One"; 
    newDerivedClass.UniqueProperty2 = "Some Thing"; 
    newDerivedClass.UniqueProperty3 = "Some Thing Else"; 

    return newDerivedClass; 
} 

he cambiado de código como sigue abajo y parece que funciona y tiene más sentido ahora:

Antiguo

public MyBaseClass GetPopulatedBaseClass() 
{ 
    var myBaseClass = new MyBaseClass(); 

    myBaseClass.BaseProperty1 = "Something" 
    myBaseClass.BaseProperty2 = "Something else" 
    myBaseClass.BaseProperty3 = "Something more" 
    //etc... 

    return myBaseClass; 
} 

Nueva

public void FillBaseClass(MyBaseClass myBaseClass) 
{ 
    myBaseClass.BaseProperty1 = "Something" 
    myBaseClass.BaseProperty2 = "Something else" 
    myBaseClass.BaseProperty3 = "Something more" 
    //etc... 
} 

Antiguo

public MyDerivedClass GetPopulatedDerivedClass() 
{ 
    var newDerivedClass = (MyDerivedClass)GetPopulatedBaseClass(); 

    newDerivedClass.UniqueProperty1 = "Some One"; 
    newDerivedClass.UniqueProperty2 = "Some Thing"; 
    newDerivedClass.UniqueProperty3 = "Some Thing Else"; 

    return newDerivedClass; 
} 

Nueva

public MyDerivedClass GetPopulatedDerivedClass() 
{ 
    var newDerivedClass = new MyDerivedClass(); 

    FillBaseClass(newDerivedClass); 

    newDerivedClass.UniqueProperty1 = "Some One"; 
    newDerivedClass.UniqueProperty2 = "Some Thing"; 
    newDerivedClass.UniqueProperty3 = "Some Thing Else"; 

    return newDerivedClass; 
} 
+0

¡Muy bien! ¡exactamente lo quiero! thx: D –

+4

cada vez que agregue una propiedad tendrá que editar esto. para que otros lean esto, sugiero que piensen en usar composición en su lugar –

Cuestiones relacionadas