3 回答
TA贡献1874条经验 获得超12个赞
您的方法签名声明该方法应该是通用的,并且不能仅针对某些具体类型覆盖它,您可以执行以下操作:
public class P2 : P1
{
public override void Run<T>(T c)
{
c.c1Prop = 1; //Is recognized since you have where T : C1 clause
var c2 = c as C2;
if (c2 != null)
{
c2.c2Prop = 2;
}
}
}
TA贡献1757条经验 获得超8个赞
当您说void Run<C2>(C2 c)那C2是泛型类型时,它不是具体类型C2。为了更清楚,请更改C2为T:
public override void Run<T>(T c)
{
c.c1Prop = 1; //Is recognized
c.c2Prop = 2; //Is NOT recognized and is an error
}
您可以访问的原因是层次结构中较早c1Prop的类型约束。where T : C1
解决这个问题的一种方法是使其P1自身通用:
public abstract class P1<T> where T : C1
{
public abstract void Run(T c);
}
这P2看起来像这样:
public class P2 : P1<C2>
{
public override void Run(C2 c)
{
c.c1Prop = 1;
c.c2Prop = 2;
}
}
TA贡献1815条经验 获得超13个赞
混淆的最初原因是在您的Run覆盖中,C2是一个类型参数- 它不是名为C2. T将其保留在覆盖方法的声明中有助于明确这一点:
public class P2 : P1
{
// Changed type parameter name from C2 to T for clarity
public override void Run<T>(T c)
{
c.c1Prop = 1;
c.c2Prop = 2;
}
}
这是绝对等价的代码,但更清楚的是发生了什么。
现在T受限于where T : C1which is how c.c1Propworks - 但它完全可行,c不会是C2. 例如,我可以写:
class OtherC1 : C1 {}
P2 p2 = new P2();
p2.Run(new OtherC1());
这显然不适用于您当前的代码 - 没有c2Propin OtherC1。
听起来您可能想要P1通用而不是Run方法。你可以有:
public abstract class P1<T> where T : C1
{
public abstract void Run(T c);
}
public class P2 : P1<C2>
{
public override void Run(C2 c)
{
c.c1Prop = 1; //Is recognized
c.c2Prop = 2; //Is NOT recognized and is an error
}
}
然后编译,所有代码都知道你只能提供一个C2(或更多派生类)到P2.Run. 所以我们前面的例子OtherC1不会再编译了(这是我们想要的)。
- 3 回答
- 0 关注
- 121 浏览
添加回答
举报