【问题标题】:C# Inherited member variables behaving undexpectedlyC# 继承的成员变量行为异常
【发布时间】:2010-05-19 16:35:03
【问题描述】:

如果我有这样的课程:

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”!为什么会这样,如果不在构造函数中设置变量,我怎样才能让它按我想要的方式工作?

【问题讨论】:

  • 问题是 C++;标签说 C#。是哪个?
  • 我看不出它在哪里说 C++。如果这是 C++,就会有一个 ;在我的课程的右括号;D
  • 第三段,非代码块:“Visual C++ 会告诉我 B.fe 隐藏了 A.fe,所以我应该使用 new 关键字。所以我将 B 类更改为:”跨度>

标签: c# class inheritance variables member


【解决方案1】:

这就是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"; } }
}

【讨论】:

  • 非常感谢,这是我需要知道的。我会假设它不一定是一个属性。
  • @Nilbert:你不能覆盖字段——那没有意义。所以你必须使用属性(或方法)。
  • 哦,好的,非常感谢。当计时器允许我这样做时,这将被标记为答案。
【解决方案2】:

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

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 方法中),它与基类版本一起使用(这是newoverride 的区别)。

现在,您还可以修改您的blah 方法,将其输入转换为B,从而访问您的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"
}

但我不建议这样做。

【讨论】:

    【解决方案3】:
    class A {
    
    public virtual string fe { get { return "A"; } set {} }
    
    }
    
    class B {
     public override string fe { get { return "B"; } set {} }
    }
    

    是你需要的...

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

    【讨论】:

      猜你喜欢
      • 2016-08-16
      • 2020-08-18
      • 1970-01-01
      • 2012-02-13
      • 1970-01-01
      • 1970-01-01
      • 2016-12-03
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多