方法重载:漏斗调用派生类参数重载

时间:2010-02-09 13:16:46

标签: c# overloading

好的,我正在尝试执行以下操作:

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

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

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

当Base类传递给方法时,调用方法的Derived类版本。基类是抽象的,所以理论上这应该是可能的吗?

在某人说出有关在类本身上重载方法的事情之前,方法内部的逻辑依赖于大量不同的条件,其中没有一个是相关的,并且没有一个直接与Base / Derived类相关(例如作为登录状态等。)

3 个答案:

答案 0 :(得分:6)

如果发现双重调度过于干扰,可以通过反射调用方法并动态解决正确的重载。

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出现动态关键字时,这将更加容易:

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

    dynamic dynamicThis = this;

    return (bool)dynamicThis.ValidAdvert(item as dynamic);
}

答案 1 :(得分:5)

使用double dispatch的理想场所:

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

答案 2 :(得分:0)

我不确定你将如何拥有一个实际上不是派生类实例的基类实例。由于基类是抽象的,因此无法实例化。我想它会匹配任何没有特定签名的派生类,但这似乎不是你想要的。