Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When implementing an interface which define a base class property why can't the class implementing interface return a derived class type object?

Tags:

c#

inheritance

Lets create some interfaces

public interface ITimeEventHandler
    {
        string Open();
    }

    public interface IJobTimeEventHandler : ITimeEventHandler
    {
        string DeleteJob();
    }

    public interface IActivityTimeEventHandler : ITimeEventHandler
    {
        string DeleteActivity();
    }



    public interface ITimeEvent
    {
        ITimeEventHandler Handler { get; }
    }

    public interface IJobTimeEvent : ITimeEvent
    {
        int JobID { get;  }
    }

Create a class

public class JobTimeEvent : IJobTimeEvent
    {
        public int JobID
        {
            get; internal set;

        }

        public IJobTimeEventHandler Handler
        {
            get; internal set;
        }

    }

My question is .. when implementing an interface which define a base class property why cant the class implementing interface return a derived class type object ??

For ex in class JobTimeEvent, IJobtimeEvent needs a property of type ITimeEventHandler but why IJobTimeEventHandler type is not allowed which derived from ITimeEventHandler

like image 323
Deepak Avatar asked Apr 01 '10 17:04

Deepak


2 Answers

This is a duplicate of

Why C# doesn't allow inheritance of return type when implementing an Interface

The feature you want is called "return type covariance", and it is a frequently requested feature in C#. It is not supported by the CLR and we have no plans to implement it in C#, sorry!

like image 173
Eric Lippert Avatar answered Sep 28 '22 07:09

Eric Lippert


Edit: The following is equally valid for get/set properties, so the fact that you can't declare fields in an interface is not fundamental to the points I'm making.

In your case, ITimeEvent.Handler is a field, which means you could do the following:

ITimeEvent x = ...;
IJobTimeEventHandler handler = ...;
x.Handler = handler;

If x was assigned an object of (concrete) type JobTimeEvent, and JobTimeEvent.Handler was declared as a JobTimeEventHandler, the the assignment above would fail. This is an example of how contravariance is not a safe operation for assignment.

If instead you had the following:

interface ITimeEvent
{
    IJobTimeEventHandler Handler { get; }
}

Then you could easily do this:

class JobTimeEvent : ITimeEvent
{
    private JobTimeEventHandler _handler;

    public IJobTimeEventHandler Handler { get { return _handler; } }
}
like image 35
Sam Harwell Avatar answered Sep 28 '22 09:09

Sam Harwell