with new method inherited how from example c# inheritance override abstract derived

new - Anulación de una propiedad abstracta con un tipo de devolución derivada en c#



override c# (6)

Tengo cuatro clases. Solicitud, DerivedRequest, Handler, DerivedHandler. La clase Handler tiene una propiedad con la siguiente declaración:

public abstract Request request { get; set; }

El DerivedHandler necesita anular esta propiedad para que devuelva DerivedRequest en su lugar:

public override DerivedRequest request { get; set; }

¿Alguien tiene alguna idea sobre cómo hacer que esto funcione?


Editar: No puede cambiar el tipo en un tipo derivado, pero puede ser new :

En el tipo derivado ...

public new DerivedRequest request { get{return (DerivedRequest) base.request;} set{base.request = value;} } public override Request request { get{return base.request;} set{base.request = (DerivedRequest) value;} // Throws InvalidCastException if misused. }


En el lenguaje C #, no está permitido cambiar la firma de un método heredado, a menos que lo sustituya por otro método con el mismo nombre . Esta técnica se conoce como "ocultación de miembro" o "ocultación".

Si está utilizando .NET 2.0 o posterior, puede resolver este problema convirtiendo el tipo de devolución de la propiedad Request en un parámetro de tipo genérico de la clase Handler . La clase DerivedHandler especificaría entonces la clase DerivedRequest como argumento para ese parámetro de tipo.

Aquí hay un ejemplo:

// Handler.cs public class Handler<TRequest> where TRequest : Request { public TRequest Request { get; set; } } // DerivedHandler.cs public class DerivedHandler : Handler<DerivedRequest> { }


Esta no es realmente una buena forma de estructurar las cosas. Haz una de las siguientes

1) Simplemente no cambie el tipo de devolución y anótelo normalmente en la subclase. En DerivedHandler puede devolver una instancia de DerivedRequest utilizando la firma de clase base de Request . Cualquier código de cliente que use esto puede elegir DerivedRequest a DerivedRequest si así lo desean.

2) Use genéricos en su lugar si no se supone que son polimórficos.

public abstract class HandlerBase<T> where T: Request { public abstract T Request {get;set;} } public class Handler: HandlerBase<Request>() public class DerivedHandler: HandlerBase<DerivedRequest>()


Esto no es teóricamente posible. La anulación debe ser covariante para el tipo de devolución (es decir, el tipo de devolución debe ser más específico o el mismo), y contravariante para el parámetro (es decir, el tipo de parámetro debe ser menos específico o el mismo). Por lo tanto, su nuevo tipo debe ser al mismo tiempo covariante y contravariante con respecto a la Request , es decir, el único tipo posible es simplemente Request .

Por esta razón, no está permitido en C # cambiar el tipo de propiedades para reemplazos.


Excepto por ocultar la propiedad original:

public new DerivedRequest Request { get;set;}

Sin embargo, desaconsejo encarecidamente eso. Esconder algo que se supone debe ser anulado invita a problemas, especialmente si la propiedad no es una simple generación automática. Además, si lo usa como una interfaz o clase base, la implementación original (en ese caso, una clase más alta en el árbol de herencia). Si está implementando una clase o interfaz abstracta, ni siquiera podrá ocultar la firma original, ya que debe implementarla.

Usualmente, si piensas en usar la new palabra clave, estás en la pista incorrecta. Hay casos en que es necesario y necesario, sin embargo, en la mayoría de los casos, no lo es.

En cambio, crea otra propiedad:

public DerivedRequest DerivedRequest {/* make adequate conversions here*/ }

De esta manera, usted está en el lado claro con respecto a OOP y obtiene su información de una manera clara.


public class Request{} public class DerivedRequest : Request{} public class Handler<T> where T : Request { public abstract T Request { get; set; } } public class DerivedHandler : Handler<DerivedRequest> { public override DerivedRequest Request { get; set; } }