C#繼承的問題

今天看到的一個問題,

感覺還蠻有意思的,

    // Question #1
    class Program
    {
        static void Main(string[] args)
        {
            int i = 13;
            string Result = B.Get(i);
            Console.WriteLine(Result);
        }
    }

    public class A
    {
        public static string Get(int Value) {
            return "A";
        }
    }

    public class B : A
    {
        public static string Get(float Value)
        {
            return "B";
        }
    }

上面這結果會是如何?


posted on 2009/7/14 01:56 | 我要推薦 | 閱讀數 : 1104 | 分類[ .Net C# Microsoft 技術相關 程式相關 ] 訂閱

Comments on this post

# re: C#繼承的問題

這個問題還真好玩@@"

我以為要覆寫方法除了要宣告NEW或是OVERRIDE,沒想到型別轉換上也有差....

Left by 星寂 on 七月 14, 2009 9:36 上午
回覆

# re: C#繼承的問題

to 星寂 :

型別轉換?全都改成int似乎也是return B囉...

(想不到這例子會是我第一次玩winform的程式 哈)

Left by hatelove on 七月 14, 2009 9:48 上午
回覆

# re: C#繼承的問題

我也是這摸覺得 靜態變數已經是類別層級變數了 應該是不受繼承影響 繼承看起來是純粹混淆用的"吧"
Left by larrynung on 七月 14, 2009 7:28 下午
回覆

# re: C#繼承的問題

剛試了一下 原來靜態變數也是有繼承效果 若不寫B的Function則透過B執行起來就是A的值 若有寫的話 透過B執行起來就是B的值 看起來也很合理
Left by larrynung on 七月 14, 2009 7:46 下午
回覆

# re: C#繼承的問題

to larrynung :

感覺有點shadows的味道,不曉得在C#裡面,shadows的關鍵字是啥..

也就是同名字的函數,強制覆寫父類別的參數個數和型態,

一切以我小孩自己說的為主就對了...

Left by hatelove on 七月 14, 2009 8:14 下午
回覆

# re: C#繼承的問題

應該是這段吧,原文來自 http://msdn.microsoft.com/zh-tw/library/435f1dw2.aspx

new 關鍵字做為修飾詞時,會明確隱藏繼承自基底類別的成員。當您隱藏繼承的成員時,該成員的衍生版本就會取代基底類別版本。雖然您可以不用 new 修飾詞來隱藏成員,但是這樣會產生警告。如果您使用 new 來明確隱藏成員,此關鍵字就會隱藏這類警告,並會記錄企圖使用衍生版本做為替代的事實。

 

Left by billchung on 七月 15, 2009 4:07 上午
回覆

# re: C#繼承的問題

另外 靜態方法應該是不能覆寫的 ,在MSDN有一段話 (http://msdn.microsoft.com/zh-tw/library/ebca9ah3.aspx)

您不能覆寫非虛擬或靜態方法。被覆寫的基底方法必須是 virtualabstractoverride

 

Left by billchung on 七月 15, 2009 4:10 上午
回覆

# re: C#繼承的問題

恩~所以靜態變數看來是只能遮蔽不能覆寫
Left by larrynung on 七月 15, 2009 9:56 上午
回覆

# re: C#繼承的問題

不好意思,因為上班不能上網,
所以現在才有時間回.

就我的想法,
這個問題跟override(覆寫)比較沒有關係,
有關的反而是overloading(多載)...

因為在class A中是Get(int)
而Class B中是Get(float)

在main中,我們呼叫Get然後丟個int進去,
結果卻是跑去執行Get(float)
而丟float還是去執行Get(float)

相反的,
假如把程式調換一下,寫成:

   public class A
    {
        public static string Get(int Value)
        {
            return "A";
        }

    }


    public class B : A
    {
        public static string Get(float Value)
        {
            return "B";
        }

    }


這時,丟int就是跑Get(int)
丟float就是跑Get(float)

但是,假如不要用繼承
直接寫一個Class,如下

    public class C
    {
        public static string Get(int Value)
        {
            return "C int";
        }

        public static string Get(float Value)
        {
            return "C float";
        }

    }


這時,丟int就是跑Get(int)
丟float就是跑Get(float)

而這可能是跟int型別的隱含轉換與繼承關係有關,
在int型別中
http://msdn.microsoft.com/zh-tw/library/5kzh1b5w%28VS.80%29.aspx
有所謂的預先定義的隱含轉換,從int轉換為long,float,double,decimal
所以上面範例中,如果把float改為long,double,decimal也會是一樣的情況.

所以當最上層的class有函數是可以允許隱含轉換的型別的話,就會是以上層的為主.

以上是我的猜測,因為不知道C#編譯器實際的運作是怎樣,所以只能這樣猜測.

只能說,有時程式並不如我們所想像的跑...
 

Left by ajun on 七月 16, 2009 12:10 上午
回覆

# re: C#繼承的問題

我試的結果就算顛倒還是都為B
跟您的不太一樣
但是把Static拿掉就回復正常
也許這問題還是要回歸到類別層級來看他
我猜也許規則如下
當本身的類別有自己的靜態函式(或可藉由隱含轉換Cover)
則會使用本身的靜態函式
若本身類別無自己的靜態函式
則使用父類別的靜態函式
Left by larrynung on 七月 16, 2009 12:58 下午
回覆

# re: C#繼承的問題

to hatelove :
如同Bill叔叔po的那篇,我以為應該是要宣告new(如果簽名都一樣),以簽名不同來說,我一開始以為是overloading,結果run起來之後發現不是。

Left by alonstar on 七月 19, 2009 7:59 下午
回覆

回應:

Please add 1 and 8 and type the answer here: