C#通用扩展方法拳击转换问题

时间:2016-09-02 06:45:39

标签: c# generics boxing

我正在使用C#迁移/重写一些Java泛型。我收到一个我不理解的错误。

(这部分是基于继承的组合实验,以限制不需要某些功能的子类的膨胀,但它也只是一个更好地理解C#泛型的实验。)

注意:实际的子类实现实际上像我期望的那样工作,它只是不编译的扩展方法。

父类:

public abstract class PageObject<T> where T : PageObject<T>
{

    protected IWebDriver WebDriver => ServiceLocator.GetWebDriver();

    public PageObject()
    {
        PageFactory.InitElements(WebDriver, this);
    }

    // ... more stuff, but the constructor is the important thing that keeps
    // me using an abstract parent class. There are some abstract methods
    // that return T so the child classes can return "this" in a fluent api.
}

界面:

public interface IHasCustomLoadCondition<T> where T : PageObject<T>
{
    bool IsLoaded();
}

和扩展方法,这是发生错误的地方:

public static T WaitForCustomPageLoad<T>(this T page) where T : IHasCustomLoadCondition<T>
{
    wait.Until<bool>((d) =>
    {
        return page.IsLoaded();
    });
    return page;
}

错误消息:

The type 'T' cannot be used as type parameter 'T' in the generic type or method
'IHasCustomLoadCondition<T>'. There is no boxing conversion or type parameter conversion
from 'T' to 'PageObject<T>'.

2 个答案:

答案 0 :(得分:4)

既然你有这个声明:

public interface IHasCustomLoadCondition<T> where T : PageObject<T>
                                            ^---------------------^

您必须确保将此约束带入派生接口,实现在同一T上也是通用的类和方法,因此此方法:

public static T WaitForCustomPageLoad<T>(this T page) where T : IHasCustomLoadCondition<T>

还必须具有此约束:

public static T WaitForCustomPageLoad<T>(this T page)
    where T : PageObject<T>, IHasCustomLoadCondition<T>

基本上:

public static T WaitForCustomPageLoad<T>(this T page) where T : IHasCustomLoadCondition<T>
                                      ^                                                 ^
                                      |                                                 |
                                      +-------- constraints must be compatible ---------+

答案 1 :(得分:0)

您对接口和方法都有不明确的泛型类型限制。

public interface IHasCustomLoadCondition<T> where T : PageObject<T>

这意味着它可能像这样,因为你将PageObject的泛型类型参数约束到同一个类:

public TestClass : IHasCustomLoadCondition<PageObject<PageObject<PageObject...

如果不是错误,那么您应该按以下方式修改方法声明:

public static T WaitForCustomPageLoad<T, T1>(this T page) 
where T : IHasCustomLoadCondition<T1>
where T1 : PageObject<T1>

与原始来源一样,您的约束意味着“通用类型参数应为IHasCustomLoadCondition<IHasCustomLoadCondition<IHasCustomLoadCondition...

但接口约束意味着IHasCustomLoadCondition的泛型类型参数应为PageObject,但PageObject不实现IHasCustomLoadCondition

我希望,这是可以理解的解释。