为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

C#
慕仙森 2022-01-16 14:37:55
如果这已经被问过了,请原谅我。我搜索了它,但找不到任何东西。似乎编译器被这段代码弄糊涂了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 也会很烦人。
查看完整描述

3 回答

?
HUWWW

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;

            }

        }

    }


查看完整回答
反对 回复 2022-01-16
?
陪伴而非守候

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;

    }

}


查看完整回答
反对 回复 2022-01-16
?
萧十郎

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不会再编译了(这是我们想要的)。


查看完整回答
反对 回复 2022-01-16
  • 3 回答
  • 0 关注
  • 121 浏览

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信