2013-04-27 78 views
0

以下代码显示使用ref关键字的传递参考示例。按值传递vs按多态传递参考

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关键字,这将是通过值传递和输出I得到。将10和15

然而,随着ref关键字,我实际上得到的5的输出和15!为什么没有引用的代码指向classA中的方法,而带ref的代码指向classB中的方法?我猜它必须做多态的事情 - classB继承class A,但你如何解释它?

+1

阅读您的编译器警告;他们告诉你这里发生了什么事。 – 2013-04-28 14:44:35

回答

2

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

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

2

ClassB.MethodB不覆盖ClassA.MethodB,并且您从ClassA引用调用MethodB。

,如果你想ClassB.MethodB到被调用在这种情况下,你必须加上override关键字,如果不是.NET将其识别为另一种方法。

2

这不是ref的问题与否。

你有ClassA a = new ClassB();,即a具有编译时类型ClassA,但运行时类型派生程度更高,即ClassB

1:您调用virtual方法MethodA。这种方法ClassB覆盖,所以因为虚拟调度的,用于重写的实现。

2:您调用virtual方法MethodB。此方法是(继承但是)不是重写。因此使用其在ClassA中的“原始”(并且唯一的)实现。正如我所说,ClassA是编译时类型aClassB intodces 方法具有相同的名称和签名是不相关的。也许你错误地省略了关键字override?编译器给你一个隐藏方法的警告。

总是避免引入隐藏从基类继承的现有成员的新成员(在派生类中)。相反,尝试使用新名称(识别符)或新签名,这与现有成员不冲突。或者,也许根本不是从基类派生的。