Understanding Variance (Contravariance)

Viewed 86

I'm trying to understand how Variance works. I have created a IRegistry interface which supports a Contravarint TDomainEvent and a Contravariant TDomainContraVariant. The thing is that the TDomainEvent extends a IDomainEvent and the TDomainContraVariant extends an IDomainEventHandler<TDomainEvent>.

For some reason I get errors saying that it is not possible to convert TDomainContraVariant to IDomainEventHandler<IDomainEvent>, which should be possible as a TDomainEvent extends an IDomainEvent.

using System;
using System.Collections.Generic;

public interface IDomainEvent {}
public class ProductSetCreatedEvent : IDomainEvent {}
public class VersionCreatedEvent : IDomainEvent {}

public class ProductSetCreatedEventHandler : IDomainEventHandler<ProductSetCreatedEvent> {}
public class VersionCreatedEventHandler : IDomainEventHandler<VersionCreatedEvent> {}

public interface IDomainEventHandler<in TDomainEvent> where TDomainEvent : IDomainEvent {}


public interface IRegistry<in TDomainEvent, in TDomainContraVariant>
    where TDomainEvent : IDomainEvent
    where TDomainContraVariant : IDomainEventHandler<TDomainEvent>
{
    void Add(TDomainContraVariant element);
}


public class Registry<TDomainEvent, TDomainContraVariant> : IRegistry<TDomainEvent, TDomainContraVariant>
    where TDomainEvent : IDomainEvent
    where TDomainContraVariant : IDomainEventHandler<TDomainEvent>
{
    private IList<IDomainEventHandler<IDomainEvent>> list;

    public Registry()
    {
        this.list = new List<IDomainEventHandler<IDomainEvent>>();
    }

    public void Add(TDomainContraVariant element)
    {
        this.list.Add(element);
    }
    
    public IList<IDomainEventHandler<IDomainEvent>> Get()
    {
        return this.list;
    }
}
                    
public class Program
{   
    private static Registry<IDomainEvent, IDomainEventHandler<IDomainEvent>> list = new Registry<IDomainEvent, IDomainEventHandler<IDomainEvent>>();
    
    public static void Main()
    {       
        IDomainEventHandler<ProductSetCreatedEvent> eventHandler = new ProductSetCreatedEventHandler();
        AddToRegistry<ProductSetCreatedEvent, IDomainEventHandler<ProductSetCreatedEvent>>(eventHandler);
    }
    
    public static void AddToRegistry<TDomainEvent, TDomainContraVariant>(TDomainContraVariant cesto)
        where TDomainEvent : IDomainEvent
        where TDomainContraVariant : IDomainEventHandler<TDomainEvent>
    {
        list.Add(cesto);
    }
}
0 Answers
Related