通过值传递值与通过引用传递多态

时间:2013-04-27 21:11:41

标签: c# polymorphism pass-by-reference pass-by-value

以下代码显示了使用ref关键字的参考传递示例。

class Program
{
    static void Main(string[] args)
    {
        int c1 = 10;
        ClassC c2 = new ClassC(10);
        ClassA a = new ClassB();

        a.MethodA(ref c1); Console.WriteLine(c1);
        a.MethodB(ref c2); Console.WriteLine(c2.getC());

        Console.Read();
    }
}

class ClassA //base class
{
    public virtual void MethodA(ref int c1)
    {
        c1 = c1 + 5;
    }
    public virtual void MethodB(ref ClassC c2)
    {
        c2.setC(c2.getC() + 5);
    }
}

class ClassB : ClassA  //ssubclass
{
    public override void MethodA(ref int c1)
    {
        c1 = c1 - 5;
    }
    public void MethodB(ref ClassC c2)
    {
        c2.setC(c2.getC() - 5);
    }
}


class ClassC //just a class with a variable c with get/set methods
{
    protected int c;
    public ClassC(int CValue) { c = CValue; }
    public void setC(int cnew) { this.c = cnew; }
    public int getC() { return c; }
}

如果没有ref关键字,它将按值传递,我得到的输出将是10和15。

但是,使用ref关键字,我实际得到的输出为5和15!为什么没有ref的代码指向classA中的方法,而带有ref的代码指向classB中的方法?我猜它必须对多态性做一些事情 - classB继承class A,但你怎么解释它?

3 个答案:

答案 0 :(得分:2)

  

为什么没有ref的代码指向的方法   classA,而带有ref的代码指向classB中的方法?

您的代码调用了ClassB.MethodAClassA.MethodB。总是。没有与ref ...

达成协议

答案 1 :(得分:2)

ClassB.MethodB不会覆盖ClassA.MethodB,而是从ClassA引用调用MethodB。

如果你希望在这种情况下调用ClassB.MethodB,你必须添加override关键字,如果不是.net将其识别为另一种方法。

答案 2 :(得分:2)

这不是ref的问题。

您有ClassA a = new ClassB();,即a具有编译时类型ClassA,但运行时类型更加派生,即ClassB

1:您调用virtual方法MethodA。此方法 ClassB覆盖,因此,由于虚拟调度,使用了重写的实现。

2:您拨打virtual方法MethodB。此方法是(继承但是) 重写。因此,使用ClassA中的“原始”(且仅)实现。正如我所说,ClassAa的编译时类型。 ClassB使用相同名称和签名引入 方法的事实无关紧要。也许你错误地省略了override关键字?编译器给出了关于隐藏方法的警告。

始终避免引入一个新成员(在派生类中),该成员隐藏从基类继承的现有成员。相反,尝试使用新名称(标识符)或新签名,它不会与现有成员冲突。或者根本不是从基类派生的。