Перегрузка метода: вызов последовательности к перегрузке аргумента производного класса - PullRequest
5 голосов
/ 09 февраля 2010

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

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

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

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

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

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

Ответы [ 3 ]

6 голосов
/ 09 февраля 2010

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

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 , хотя вызов метода с помощью отражения медленнее, чем непосредственный вызов метода (если метод вызывается менее чем несколько сотен раз в секунду, это не потребует дополнительных затрат) у него есть то преимущество, что вам не нужно изменять иерархию классов, как в шаблоне Double Dispatch.

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

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

    dynamic dynamicThis = this;

    return (bool)dynamicThis.ValidAdvert(item as dynamic);
}
5 голосов
/ 09 февраля 2010

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

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);
}
0 голосов
/ 09 февраля 2010

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

...