Перегрузка метода: направьте призывают к перегрузке аргумента производного класса

Хорошо, я пытаюсь сделать следующее:

        protected bool ValidAdvert(Base item)
        {
            throw ThisIsAnAbstractClassException();
        }

        protected bool ValidAdvert(Derived1 item)
        {
            return ADerived1SpecificPredicate;
        }

        protected bool ValidAdvert(Derived2 item)
        {
            return ADerived2SpecificPredicate;
        }    

И имейте версии Производного класса метода быть названными, когда Базовый класс будет передан методу. Базовый класс абстрактен, таким образом, это, в теории, должно быть возможно?

Прежде чем кто-то скажет что-то о перегрузке метода на самих классах, логика в методах полагается на большое количество различных условий, ни одно из которых не связано, и ни один из который связанный с Основой/Производным классом непосредственно (такой как состояние входа в систему, и т.д.)

5
задан Ed James 9 February 2010 в 13:16
поделиться

3 ответа

Если двойная отправка окажется слишком навязчивой, то можно вызвать метод отражением и динамически разрешить соответствующую перегрузку.

protected bool ValidAdvert(Base item)
{
    if (item.GetType() == typeof(Base))
        throw new ThisIsAnAbstractClassException();

    Type type = typeof(CurrentClass);

    MethodInfo method = type.GetMethod("ValidAdvert",
                                       BindingFlags.Instance | BindingFlags.NonPublic,
                                       null,
                                       new Type[] { item.GetType() },
                                       null);
    return (bool)method.Invoke(this, new object[] { item });
}

protected bool ValidAdvert(Derived1 item)
{
    return ADerived1SpecificPredicate;
}

protected bool ValidAdvert(Derived2 item)
{
    return ADerived2SpecificPredicate;
}

Этот паттерн называется MultipleDispatch , хотя вызов метода путем отражения медленнее, чем прямой вызов метода (это не будет перегрузкой, если метод вызывается менее нескольких сотен раз в секунду), его преимущество заключается в том, что он не требует изменения иерархии классов, как в паттерне двойной диспетчеризации.

Это будет еще проще, когда c# 4.0 выйдет с динамическим ключевым словом:

protected bool ValidAdvert(Base item)
{
    if (item.GetType() == typeof(Base))
        throw new ThisIsAnAbstractClassException();

    dynamic dynamicThis = this;

    return (bool)dynamicThis.ValidAdvert(item as dynamic);
}
6
ответ дан 13 December 2019 в 19:27
поделиться

Идеальное место для использования двойной отправки:

class Base
{
    public abstract bool IsValid(IAdvertValidator validator);
}

class Derived1 : Base
{
    public bool IsValid(IAdvertValidator validator)
    {
        return validator.ValidAdvert(this);
    }
}

class Derived2 : Base
{
    public bool IsValid(IAdvertValidator validator)
    {
        return validator.ValidAdvert(this);
    }
}

interface IAdvertValidator
{
    bool ValidAdvert(Derived1 d1);
    bool ValidAdvert(Derived2 d2);
}
5
ответ дан 13 December 2019 в 19:27
поделиться

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

0
ответ дан 13 December 2019 в 19:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: