Workaround for lack of return type covariance when overriding virtual methods

拥有回忆 提交于 2019-12-10 02:58:21

问题


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?


回答1:


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



回答2:


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.




回答3:


Because there is no great benefit in return type covariance in most cases.

If you are calling virtual Alpha.DoSomething then you really don't know if you are getting back an Alpha or a Beta so how does return type covariance help? You will have to store the result in an Alpha typed object anyhow because it's the only type that can admit Alphas or Betas.

On the other hand, if you statically know that you are calling Beta.DoSomething then you can either: directly use the returned Alpha typed object because you will be accessing common functionality or virtual methods so you don't care if it's really a Beta (the virtual call will resolve to the right type) or you can directly choose to (runtime safe) cast to Beta in order to access specific implementation.

Edit: removed the type safe issue. I barely thought it through and evidently return type covariance would be safe. The rest of the answer stands though. I can't find anything particularly interesting in this feature, at least in the way the OP wants to use it: avoid a safe cheap cast?



来源:https://stackoverflow.com/questions/25817771/workaround-for-lack-of-return-type-covariance-when-overriding-virtual-methods

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!