При реализации интерфейса, который определяет свойство базового класса, почему класс, реализующий интерфейс, не может вернуть производный объект типа класса? - PullRequest
5 голосов
/ 01 апреля 2010

Давайте создадим несколько интерфейсов

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

Создать класс

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

        }

        public IJobTimeEventHandler Handler
        {
            get; internal set;
        }

    }

У меня вопрос: при реализации интерфейса, который определяет свойство базового класса, почему класс, реализующий интерфейс, не может вернуть производный объект типа класса ??

Для ex в классе JobTimeEvent IJobtimeEvent необходимо свойство типа ITimeEventHandler, но почему не допускается тип IJobTimeEventHandler, производный от ITimeEventHandler

Ответы [ 4 ]

7 голосов
/ 01 апреля 2010

Это дубликат

Почему C # не разрешает наследование возвращаемого типа при реализации интерфейса

Требуемая функция называется «ковариация возвращаемого типа», и это часто запрашиваемая функция в C #. Он не поддерживается CLR, и мы не планируем реализовывать его в C #, извините!

2 голосов
/ 01 апреля 2010

Редактировать: Следующее в равной степени справедливо для свойств get / set, поэтому тот факт, что вы не можете объявлять поля в интерфейсе, не является фундаментальным для пунктов, которые я делаю.

В вашем случае ITimeEvent.Handler - это поле, что означает, что вы можете сделать следующее:

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

Если x был назначен объект (конкретного) типа JobTimeEvent, а JobTimeEvent.Handler был объявлен как JobTimeEventHandler, указанное выше назначение завершилось бы неудачно. Это пример того, как контравариантность не является безопасной операцией для присваивания.

Если вместо этого у вас было следующее:

interface ITimeEvent
{
    IJobTimeEventHandler Handler { get; }
}

Тогда вы могли бы легко сделать это:

class JobTimeEvent : ITimeEvent
{
    private JobTimeEventHandler _handler;

    public IJobTimeEventHandler Handler { get { return _handler; } }
}
0 голосов
/ 01 апреля 2010

Если вы хотите, чтобы поля, которые вы определили, действительно были свойствами, вы можете сделать что-то вроде этого ...

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

... если вы пытаетесь сделать что-то другое, вам нужно будет предоставить более подробную информацию по вашему вопросу.

0 голосов
/ 01 апреля 2010

Может возвращать класс этого типа, но он должен удовлетворять контракту интерфейса ITimeEvent и возвращать его, говоря, что он типа ITimeEventHandler. Предлагаем использовать свойство этого типа с полем поддержки производного типа.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...