C# 继承的成员变量行为异常

发布于 2024-09-02 03:43:35 字数 568 浏览 5 评论 0原文

如果我有一个这样的类:

class A {
    public string fe = "A";
}

以及一个从它继承的类,如下所示:

class B : A {
    public string fe = "B";
}

Visual C# 会告诉我 B.fe 隐藏了 A.fe,所以我应该使用 new 关键字。所以我将类 B 更改为如下所示:

class B : A {
    public new string fe = "B";
}

然后我有一个接受 A 的函数(但是,由于继承,也将接受 B),如下所示:

class D {
    public static void blah(A anAObject) {
        Console.Writeline(A.fe);
    }
}

即使当我向它传递 B 对象的实例时,它毫无疑问地接受,它会打印“A”!为什么会这样,如何才能让它按我想要的方式工作而不在构造函数中设置变量?

If I have a class like this:

class A {
    public string fe = "A";
}

And a class that inherits from it like so:

class B : A {
    public string fe = "B";
}

Visual C# will tell me that B.fe hides A.fe so I should use the new keyword. So I change class B to look like:

class B : A {
    public new string fe = "B";
}

And then I have a function that takes an A (but, by virtue of inheritance, will also take a B) like this:

class D {
    public static void blah(A anAObject) {
        Console.Writeline(A.fe);
    }
}

Even when I pass it an instance of a B object, which it will take without question, it will print "A"! Why is this, and how can I make it work how I want without setting the variable in the constructor?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

小帐篷 2024-09-09 03:43:35

这就是overridenew 之间的区别。 new 定义了一个与基类中的成员同名的成员。它不会覆盖该成员。因此,如果您有一个需要 A 实例的方法,它将采用 A.fe 的值,而不是派生类中同名的成员。

使用带有 override 的属性来代替:

class A {
    public virtual string fe { get { return "A"; } }
}

class B : A {
    public override string fe { get { return "B"; } }
}

That's the difference between override and new. new defines a member which happens to have the same name as a member in the base class. It doesn't override that member. So if you have a method that expects an A instance, it will take the value of A.fe and not the member in the derived class with the same name.

Use a property with override instead:

class A {
    public virtual string fe { get { return "A"; } }
}

class B : A {
    public override string fe { get { return "B"; } }
}
梦回梦里 2024-09-09 03:43:35

如果您希望您的 fe 成员可以被派生类覆盖,而不必使用 new 关键字(这就是您看到所看到的行为的原因),只需在基类中将其声明为virtual。那么您的代码将如下所示:

public class A
{
    public virtual string fe
    {
        get { return "A"; }
    }
}

public class B
{
    public override string fe
    {
        get { return "B"; }
    }
}

请注意,这需要将 fe 设为属性,因为成员字段不能声明为virtual

为什么您没有获得所需行为的解释是,new 关键字仅在编译时将变量声明为派生类的情况下覆盖继承的成员。如果它在编译时声明为基类(因为 anAObject 位于您的 blah 方法中),则它与基类版本一致(这就是区分 new 来自覆盖)。

现在,您还修改您的 blah 方法,将其输入转换为 B,从而访问您的 new < code>fe:

public static void blah(A anAObject) {
    var aBObject = anAObject as B;
    if (aBObject != null)
        Console.WriteLine(aBObject.fe); // would print "B"
    else
        Console.WriteLine(anAObject.fe); // would print "A"
}

但我不推荐这样做。

If you want your fe member to be overridable by derived classes without having to use the new keyword (which is why you're seeing the behavior you're seeing), just declare it virtual in the base class. Then your code would look like this:

public class A
{
    public virtual string fe
    {
        get { return "A"; }
    }
}

public class B
{
    public override string fe
    {
        get { return "B"; }
    }
}

Notice that this required making fe a property, since member fields cannot be declared virtual.

The explanation for why you're not getting the behavior you want is that the new keyword only overrides an inherited member in the event that a variable is declared as the derived class at compile time. If it's declared as the base class at compile time (as anAObject is in your blah method), it goes with the base class version (this is what differentiates new from override).

Now, you also could modify your blah method to cast its input to a B, thereby accessing your new fe:

public static void blah(A anAObject) {
    var aBObject = anAObject as B;
    if (aBObject != null)
        Console.WriteLine(aBObject.fe); // would print "B"
    else
        Console.WriteLine(anAObject.fe); // would print "A"
}

But I would not recommend this.

甜警司 2024-09-09 03:43:35
class A {

public virtual string fe { get { return "A"; } set {} }

}

class B {
 public override string fe { get { return "B"; } set {} }
}

就是你所需要的...

AFAIK 在 D.blah() 中,对象正在转换为 A 类型 &由于基值没有用 virtual 关键字标记,因此它的行为类似于 A &即使类型是 B,也不是 B...

class A {

public virtual string fe { get { return "A"; } set {} }

}

class B {
 public override string fe { get { return "B"; } set {} }
}

is what you need...

AFAIK in the D.blah() the object is getting cast of type A & since the base value is not marked with the virtual keyword, it would behave as A & not as B even if the type is B...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文