Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Workaround for lack of return type covariance when overriding virtual methods

is there any way to 'hack' or 'coerce' covariant overrides in to C#?

For example:

public class Alpha {
    public virtual Alpha DoSomething() {
        return AlphaFactory.GetAlphaFromSomewhere();
    }
}
public class Beta : Alpha {
    public override Beta DoSomething() {
        return BetaFactory.GetBetaFromSomewhere();
    }
}

Unfortunately, C# doesn't support this (which seems a bit ridiculous, but that's neither here nor there).

I thought I might have an answer with method hiding:

new public Beta DoSomething() {
    return BetaFactory.GetBetaFromSomewhere();
}

But this doesn't add the entry in to the 'vtable', it just basically declares a brand new method with the same name, and as such means that accessing Betas through a pointer to an Alpha will call Alpha.DoSomething().

So, any good tricks?

like image 270
Xenoprimate Avatar asked Sep 12 '14 22:09

Xenoprimate


People also ask

Is it possible to override co variant return types?

Covariant return type works only for non-primitive return types. From Java 5 onwards, we can override a method by changing its return type only by abiding the condition that return type is a subclass of that of overridden method return type.

What is covariant return type in method overriding?

The covariant return type specifies that the return type may vary in the same direction as the subclass. Before Java5, it was not possible to override any method by changing the return type.


2 Answers

You can do some pretty zany stuff with generics.

public class Alpha<T> where T: Alpha<T> {
    public virtual T DoSomething() {
        throw new NotImplementedException();
    }
}
public class Beta : Alpha<Beta> {
    public override Beta DoSomething() {
        throw new NotImplementedException();
    }
}
like image 146
recursive Avatar answered Sep 22 '22 13:09

recursive


You can always wrap the method inside another method

public class Alpha {
    public virtual Alpha DoSomething() {
        return AlphaFactory.GetAlphaFromSomewhere();
    }
}
public class Beta : Alpha {
    private Beta Helper() {
        return BetaFactory.GetBetaFromSomewhere();
    }
    public Beta DoSomething() {
        return Helper();
    }
    public override Alpha DoSomething() {
        return Helper();
    }
}

If there are lots of methods though, you might want to autogenerate these wrappers. If that's too demanding, the solution of @recursive is all there is left.

like image 20
chtenb Avatar answered Sep 21 '22 13:09

chtenb