es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

No se puede convertir desde el error en la estructura simple de la clase.

Tengo las siguientes relaciones de clase:

    public interface ICapability
    {
    }

    public interface IBaseService<T> where T : ICapability
    {
    }

    public abstract class BaseService<out T> : IBaseService<T> where T : ICapability
    {
       // modificado...
       T MapEventToCapability(dynamic eventData, T capability);
    }

    public class SomeCapability : ICapability
    {
    }

    public partial class Service1 : BaseService<SomeCapability>
    {
        public Service1()
        {
        }
    }

    public class ServiceResolver 
    {
        public void Register(BaseService<ICapability> serviceToRegister)
        {
        }
    }

Intento invocar el método Register, pasando un nuevo servicio1 como se muestra:

var b = new ServiceResolver();
var c = new Service1();

b.Register(c);

Sin embargo, obtengo un error de tiempo de compilación en c en la llamada a Register como sigue:

No se puede convertir Service1 a BaseService<ICapability>

Supuse que debido a que Service1 es del tipo BaseService y que SomeCapability es del tipo ICapability, esto no sería un problema.

Intenté hacer una conversión a BaseService, así como intenté cambiar el parámetro de entrada en Register para que sea un IBaseService y nuevamente hacer una conversión, pero luego obtengo un error en tiempo de ejecución.

Tags:  , ,

Answer

  1. Avatar for davy.ai

    El problema radica en el uso de covarianza y contravarianza en la jerarquía de clases. La clase BaseService se declara con un modificador de covarianza en el parámetro de tipo T, lo que permite que las clases derivadas, como Service1, sean tratadas como instancias de la clase base, pero solo en posiciones de salida (como valores de retorno). Sin embargo, al pasar una instancia de Service1 a un método que espera un parámetro BaseService, que es invariante (es decir, ni covariante ni contravariante), el compilador no puede garantizar la seguridad de tipo, ya que no puede estar seguro de que el parámetro de tipo SomeCapability de Service1 sea compatible con la restricción de tipo ICapability del parámetro BaseService.

    Para resolver este problema, puedes eliminar el modificador de covarianza de la clase BaseService, o usar una interfaz con un modificador de covarianza en lugar de la clase abstracta:

    public interface IBaseService<out T> where T : ICapability
    {
    }
    
    public class Service1 : IBaseService<SomeCapability>
    {
        public Service1()
        {
        }
    }
    
    public class ServiceResolver 
    {
        public void Register(IBaseService<ICapability> serviceToRegister)
        {
        }
    }
    

    Ahora, Service1 se puede pasar como parámetro a Register, ya que implementa la interfaz IBaseService, que es covariante con IBaseService.

Comments are closed.