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

4

3 回答 3

6

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

改为使用属性override

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

class B : A {
    public override string fe { get { return "B"; } }
}
于 2010-05-19T16:39:35.077 回答
2

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

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

但我不会推荐这个。

于 2010-05-19T16:39:15.843 回答
1
class A {

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

}

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

是你需要的...

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

于 2010-05-19T16:38:59.167 回答