2012-10-19 96 views
2

正如每個人都知道在類中使用virtual關鍵字允許我們在其派生的子類中覆蓋它。然而,方法仍然必須堅持相同的簽名,例如返回值,參數等。使用虛擬覆蓋方法簽名

問題:在C#中,我怎樣才能重寫簽名呢?這可能嗎?

謝謝。

回答

4

這是不可能的。如果你需要的話,你可以創建一個重載。

編輯

爲了使我的情況下對new,請考慮一下,你有一個基本對象的情況下,和一個從它繼承。通過在您試圖「更改」方法簽名的方法之前放置new,您實際上正在浪費四個關鍵筆劃。現在

public class Base { 
    public string Foo() { return null; } 
} 

public class Inherited : Base { 
    public new int Foo() { return 0; } 
} 

Inherited有兩種方法:

public string Foo() { return null; } 
public int Foo() { return 0; } 

你實際上並沒有改變方法簽名。因此,關鍵字new甚至不需要。你會得到同樣的效果沒有它:

public class Inherited : Base { 
    public int Foo() { return 0; } 
} 

採用newoverride a non-virtual member of a base class

public class Base { 
    public string Foo() { return null; } 
} 

public class Inherited : Base { 
    public new string Foo() { return "Something else..."; } 
} 

但是你會遇到這個問題,如果你沒有注意這個微妙。通過virtual,您可以獲得一個虛擬查找表,將您的功能映射到正確的呼叫。用new,你不會。如果您通過Inherited需要Base對象(當然這會起作用),Base類的Foo()將被調用!不,Inherited「覆蓋」Foo()

這與重寫虛擬成員的行爲不同。

public static class MyClass { 
    public string MyMethod (Base @base) { 
     return @base.Foo(); 
    } 
} 

[Test] 
public void then_it_should_return_non_null() { 
    var obj = new Inherited(); 
    var result = MyClass.MyMethod(obj); // obj will get upcasted to Base 
    Assert.That (result, Is.EqualTo(obj.Foo())); // Assert fails! 
} 

[Test] 
public void inherited_should_return_correct_value() 
{ 
    var obj = new Inherited(); 
    var result = obj.Foo(); // will access the "new" method, hiding Base's implementation 
    Assert.That (result, Is.Not.Null); // Assert passes! 
} 
0

您可以用new關鍵字隱藏舊的實現。但是,基類將無法看到它。

class Base { 
    public string Foo() { } 
} 

class Sub : Base { 
    new public int Foo() { } 
} 

new只在呼叫簽名相同時才需要。

+0

雖然這並不會改變簽名。 –

+0

@ JamesD'Angelo是的,它可以改變簽名。 –

+0

@ JamesD'Angelo http://msdn.microsoft.com/en-us/library/435f1dw2.aspx –

0

到那時,你只是在做一個新的方法。但是,如果你想簡單地用新方法簽名創建一個新方法,然後調用base.OtherMethod(param1,param2)...你可以。

我想說明的一點是,如果你打算創建具有相同名稱的一種方法,在基類,但有一個不同的簽名但你還是想僅僅調用基類,然後你可以。

例如:

// In base class - note, the "virtual" isn't necessary. 
public virtual void PostMessage(string message, DateTime entryDate) { ... } 

那你認爲......「哦,我想這個基類曾經對自己沒有要求的日期是方法的重載......我該怎麼辦? !」

// In your sub-class. 
public void PostMessage(string message) 
{ 
    base.PostMessage(message, DateTime.Now); 
} 
+0

感謝您的評論。我看到你在說什麼,但沒有得到最後的聲明「,然後調用base.OtherMethod(param1,param2)...你可以。」你能給我一些想法嗎? –

+0

我會編輯答案更清晰。 –

0

您正在討論創建新方法。如果名稱相同,但參數不同(返回類型和參數的類型和參數數量),則實際上會超載。