Deepak
Deepak

Reputation: 117

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

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

Upvotes: 5

Views: 2893

Answers (4)

Eric Lippert
Eric Lippert

Reputation: 659956

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!

Upvotes: 7

Matthew Whited
Matthew Whited

Reputation: 22433

If you want the fields you definded to really be properties you could do something like this...

public interface ITimeEvent
{
    ITimeEventHandler Handler { get; set; }
}
public interface IJobTimeEvent : ITimeEvent
{
    int JobID { get; set; }
}

public class JobTimeEvent : IJobTimeEvent
{
    public JobTimeEvent()
    {
        //these are currently useless because they are the default values
        this.JobID = 0;
        this.Handler = null;
    }
    public int JobID { get; set; }
    public ITimeEventHandler Handler { get; set; }
}

... if you are trying to do something different you will need to provide more details to your question.

Upvotes: 0

Sam Harwell
Sam Harwell

Reputation: 99859

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; } }
}

Upvotes: 2

David M
David M

Reputation: 72840

It can return a class of this type, but it must satisfy the contract of the ITimeEvent interface and return it saying it's of type ITimeEventHandler. Suggest you use a property of this type, with a backing field of the derived type.

Upvotes: 0

Related Questions