2013-04-27 98 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?編譯器給你一個隱藏方法的警告。

總是避免引入隱藏從基類繼承的現有成員的新成員(在派生類中)。相反,嘗試使用新名稱(識別符)或新簽名,這與現有成員不衝突。或者,也許根本不是從基類派生的。