Error on casting a instance to Generic parent

Viewed 49

I have a problem to cast to generic parent, this is my codes

    public interface IEvent
    {
    }

    public interface IEventHandler<TEvent> where TEvent : IEvent
    {
        Task Handle(TEvent evt);
    }

    public class PersonCreatedEvent : IEvent
    {
        public int Id { get; set; }
    }

    public class PersonCreatedEventHandler : IEventHandler<PersonCreatedEvent>
    {
        public async Task Handle(PersonCreatedEvent evt)
        {
            Console.WriteLine("done");
        }
    }

And my code for casting is this:

    var handler = new PersonCreatedEventHandler();

    // exception occurred on this line 
    var cast = (IEventHandler<IEvent>)handler;

But I got exception when I want to cast instance.

Unable to cast object of type 'TestProject.ClientApi.PersonCreatedEventHandler' to type 'TestProject.ClientApi.IEventHandler`1[ElearnoInstitute.Endpoint.ClientApi.IEvent]'.

Why I get this exception? and how can resolve this problem.

1 Answers

That cast operation is forbidden because it can cause inconsistency problems. This is best explained with an example.

If we declare this class:

public class TestCreatedEvent : IEvent {

}

If your code were to be valid, we could do something like this:

var handler = new PersonCreatedEventHandler();
var cast = (IEventHandler<IEvent>)handler;
cast.Handle(new TestCreatedEvent());

We are passing an instance of something that's not a PersonCreatedEvent to the handler, that is a IEventHandler<PersonCreatedEvent> but not a IEventHandler<TestCreatedEvent>. The C# compiler gives the error to prevent that you can pass instances of another descendent type.

You can't cast types with generics to the same type but the generic being a super type. Another good example would be having a List<B>, B extending A, and having another class C also extending A. If you could cast List<B> to List<A>, you could add C instances to the casted List<A>, but originally that list is of type List<B>. Therefore, the result would be that you have C instances in a List<B>, which is a clear inconsistency.

Related