C# 没有用于覆盖特定类型的可访问扩展方法

如果这已经被问过了,请原谅我。我搜索了它,但找不到任何东西。


似乎编译器被这段代码弄糊涂了


public abstract class C1

{

    public int c1Prop;

}


public class C2 : C1

{

    public int c2Prop;

}


public abstract class P1

{

    public abstract void Run<T>(T c) where T : C1;

}


public class P2 : P1

{

    public override void Run<C2>(C2 c) 

    {

        c.c1Prop = 1; //Is recognized

        c.c2Prop = 2; //Is NOT recognized and is an error

    }

}

我不明白为什么这在功能级别不起作用。由于 C2 扩展了 C1 它没有违反 where 检查,但 C2 类型在被覆盖的方法中仍然无法识别。


对于某些背景,我在 Unity ScriptableObject 中使用了类似的模式,它不适用于泛型类,因此我无法将泛型类型提升到类级别。不过,将它移到那里似乎确实可以解决问题。


我想出的另一个潜在解决方法是一起摆脱通用方法以支持强制转换。不过,这似乎不像泛型那样富有表现力。在整个 Run 方法中的几个地方投射 c 也会很烦人。


慕仙森
浏览 122回答 3
3回答

HUWWW

您的方法签名声明该方法应该是通用的,并且不能仅针对某些具体类型覆盖它,您可以执行以下操作:&nbsp; &nbsp; public class P2 : P1&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; public override void Run<T>(T c)&nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c.c1Prop = 1; //Is recognized since you have where T : C1 clause&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; var c2 = c as C2;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (c2 != null)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; c2.c2Prop = 2;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }

陪伴而非守候

当您说void Run<C2>(C2 c)那C2是泛型类型时,它不是具体类型C2。为了更清楚,请更改C2为T:public override void Run<T>(T c){&nbsp; &nbsp; c.c1Prop = 1; //Is recognized&nbsp; &nbsp; c.c2Prop = 2; //Is NOT recognized and is an error}您可以访问的原因是层次结构中较早c1Prop的类型约束。where T : C1解决这个问题的一种方法是使其P1自身通用:public abstract class P1<T> where T : C1{&nbsp; &nbsp; public abstract void Run(T c);}这P2看起来像这样:public class P2 : P1<C2>{&nbsp; &nbsp; public override void Run(C2 c)&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; c.c1Prop = 1;&nbsp; &nbsp; &nbsp; &nbsp; c.c2Prop = 2;&nbsp; &nbsp; }}

萧十郎

混淆的最初原因是在您的Run覆盖中,C2是一个类型参数- 它不是名为C2. T将其保留在覆盖方法的声明中有助于明确这一点:public class P2 : P1{&nbsp; &nbsp; // Changed type parameter name from C2 to T for clarity&nbsp; &nbsp; public override void Run<T>(T c)&nbsp;&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; c.c1Prop = 1;&nbsp; &nbsp; &nbsp; &nbsp; c.c2Prop = 2;&nbsp; &nbsp; }}这是绝对等价的代码,但更清楚的是发生了什么。现在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{&nbsp; &nbsp; public abstract void Run(T c);}public class P2 : P1<C2>{&nbsp; &nbsp; public override void Run(C2 c)&nbsp;&nbsp; &nbsp; {&nbsp; &nbsp; &nbsp; &nbsp; c.c1Prop = 1; //Is recognized&nbsp; &nbsp; &nbsp; &nbsp; c.c2Prop = 2; //Is NOT recognized and is an error&nbsp; &nbsp; }}然后编译,所有代码都知道你只能提供一个C2(或更多派生类)到P2.Run. 所以我们前面的例子OtherC1不会再编译了(这是我们想要的)。
打开App,查看更多内容
随时随地看视频慕课网APP