Chapter 1 - Item 10 : Use the new Modifier Only to React to Base Class Updates

Effective C# (Covers C# 6.0), (includes Content Update Program): 50 Specific Ways to Improve Your C#, 3rd Edition By Bill Wagner 讀後心得

繼承體系中,子類別可以使用 new 修飾字修飾與父類別相同名稱的方法;並讓其有各自的實作。實務上濫用 new 修飾字容易造成混淆;此節提出只有在特定情況下才考慮使用 new 修飾相同名稱的方法。

1. 使用 new 修飾字造成設計混淆。

public class MyClass
{
    public void magicMethod( )
    {
        Debug.WriteLine( "MyClass" );
    }
}

public class MyOtherClass : MyClass
{
    public new void magicMethod( )
    {
        Debug.WriteLine( "MyOtherClass" );
    }
}
object c = makeObject( );

// Call through MyClass reference.
MyClass c1 = c as MyClass;
c1.magicMethod( );
    
// Call through MyOtherClass reference.
MyOtherClass c2 = c as MyOtherClass;
c2.magicMethod( );

a. c 是 MyClass。
輸出:
MyClass
throw System.NullReferenceException.
        
b. c 是 MyOherClass。
輸出:
MyClass
MyOtherClass
    
這樣的輸出結果會造成混淆,同一個物件呼叫同一個方法卻有不同的行為。
    
2. 在子類別重覆定義了父類別方法名稱時才考慮使用 new 修飾字。

class MyWidget : BaseWidget
{
    public void normalizeValues( )
    {
        // Do something
    }
}

在某一天 BaseWidget 也定義相同方法名稱時,則可以考慮使用 new 修飾字。

class MyWidget : BaseWidget
{
    public new void normalizeValues( )
    {
        // Do something
    }
}

class BaseWidget
{
    public void normalizeValues( )
    {
        // Do something
    }
}

若運氣好,BaseWidget 實作的方法剛好與子類別的實作內容一樣時,則可以在子類別呼叫父類別的實作方法。

class MyWidget : BaseWidget
{
    public new void normalizeValues( )
    {
        base.normalizeValues( );
    }
}
Note:若方法名稱相同,預設為加上 new 修飾字。
結論:
1. new 修飾字只有在特殊情況下才使用;一般情況下不使用,以免造成混淆。

2. 小心設計類別,若有讓子類別覆寫的需求;考慮定義父類別方法為抽象或虛擬方法(e.g. abastract, virtual.)。