2013-03-12 160 views
18

我有一次採訪我在那裏提出以下:方法具有相同名稱和簽名,但返回類型在C#

問題:具有相同名稱和簽名,但不同的返回類型的方法。他問我是否有可能這種類型?

是否有人可以告訴我下面的:

  1. 是上面的事情,可能在任何情況下(就像一個基類,一個在派生類中ATLEAST?)如果是的話是什麼類型呢?像編譯或運行時多態?

  2. 在編譯時多態性,如果方法的返回類型與簽名一樣也不同?但只有功能的名稱是相同的。編譯時多態性仍然是?

  3. 在重載,如果我有不同的返回類型,但方法名稱和簽名是相同的?可能嗎 ? (他問我這個問題,我回答錯:()請大家幫幫我。

謝謝

+7

什麼_your_答案,爲什麼? – Oded 2013-03-12 13:21:57

+3

這是不可能的。你可以嘗試以這種方式重載你的方法,但編譯器不會接受。 – Nolonar 2013-03-12 13:22:07

+0

@Oded:lol我只是意識到我回答不正確。我說,它被稱爲編譯時多態,在同一個類中它是不可能的,但是一個虛函數可以在基類中,我們可以覆蓋它,或者在具有不同返回類型的派生類中使用「新」關鍵字。但是,如果我們在同一個班上有這個功能,它會給出一個錯誤說,兩個功能具有相同的名稱。我在採訪時並沒有體貼周到,我只是意識到:(大聲笑這個簡單的問題,我無法回答,走了,我應該更多的工作 – Learner 2013-03-12 13:31:56

回答

30

  • 我認爲問題是關於return type covariance

    它允許一個方法返回一個更衍生型比在鹼例如類型中聲明的一個

    public interface ISomeInterface 
    { 
        object GetValue(); 
    } 
    
    public class SomeClass : ISomeInterface 
    { 
        public string GetValue() { return "Hello world"; } 
    } 
    

    這在Java,但不是在C#支撐。上述將不編譯的sinc e返回類型SomeClass.GetValuestring而不是object

    注意,僅基於返回類型,即下面你不能重載方法是無效的:

    public class SomeClass 
    { 
        public int GetValue() { return 1; } 
        public string GetValue() { return "abc"; } 
    } 
    

    你可以做使用接口類似的東西,雖然你需要明確地實現它們的歧義:

    public interface IValue<T> { T GetValue(); } 
    public class SomeClass : IValue<int>, IValue<string> 
    { 
        string IValue<string>.GetValue() { return "abc"; } 
        int IValue<int>.GetValue() { return 1; } 
    } 
    

  • 如果名稱是相同的但參數不同,那麼這是方法重載。這是一種多態性(ad-hoc多態性)。重載可以在編譯時靜態解析(除非你使用dynamic,在這種情況下,它們被延遲到運行時)。

    您可以在參數的數量和它們的種類過,所以下面都是有效的:

    public void DoSomething(int value) { } 
    public void DoSomething(string value) { } 
    public void DoSomething(int value, string value) { } 
    

    注意,你可以改變這些方法的返回類型 - 方法不僅可以重載基於它們的返回類型,但如果參數列表不同,它們可能會有所不同。

  • 這又是返回類型的協方差,並且在C#中不受支持。

  • +0

    謝謝,但在第二個問題,我很想知道,當我們說一個方法是超載。比如,我們應該首先爲該方法命名?其次,我們應該通過數字或類型來改變參數?最後,我應該有相同的返回類型嗎?否則程序根本無法編譯,那是什麼意思? C#中的概念沒有在這個權利? – Learner 2013-03-12 13:42:00

    +0

    @Divine - 重載方法名稱時必須相同,但參數列表必須不同。它們可以在參數的類型和/或數量上有所不同。不需要具有相同的返回類型,只是重載解析僅在方法的參數上完成,而不是返回類型。這意味着方法不能單獨在返回類型上重載。我已經用這些信息更新了答案。 C#允許方法重載,但不允許基於返回類型重載方法,並且不允許返回類型協方差。 – Lee 2013-03-12 13:55:48

    +0

    非常感謝,正如Todd所說的,public int DoSomething(string value){} public void DoSomething(int value,string value){}我可以有這個權利嗎?沒問題 ?但我明白它不會超載 – Learner 2013-03-12 14:08:59

    10

    int Foo() { return 1; }

    void Foo() { return; }

    在C#中,你不能有方法,他們必須比返回類型更多變化。

    如果參數不同,那麼你很好走。

    int Foo(string x) { return 1; }

    void Foo(double x) { return; }

    +0

    這完全讓我明白,非常感謝你:)乾杯 – Learner 2013-03-12 13:43:43

    +0

    順便說一句,我沒有看到多態在這裏,但我沒有坐在你的採訪。 :)真正的快速,多態會像void Foo(Animal a){..}和class Dog:Animal {}。你用狗不是動物叫Foo(aDog)。多態性可以從派生類型(Dog)到基類型(Animal)進行魔術轉換。更多的信息在這裏多形態:http://www.codeproject.com/Articles/4839/Building-Snap-In-Applications – 2013-03-12 13:48:56

    +0

    再次謝謝託德,不知何故很多事情對我來說是新的,因爲我沒有觸及3現在幾個月。再次我是一個初學者(大約2年的經驗,我仍然學習很多)...謝謝:)我正在通過這個codeproject鏈接:)乾杯 – Learner 2013-03-12 14:03:50

    5

    是的,有可能具有相同簽名但不同返回類型的多個方法,使用顯式接口實現如下所示:

    public interface I { 
        int foo(); 
    } 
    
    public class C : I { 
        double foo() { return 2.0; } 
        int I.foo() { return 4; } 
    } 
    
    +0

    謝謝皮特:)它是一個很好的信息:)乾杯 – Learner 2013-03-12 13:44:46

    6

    雖然返回類型協方差在C#中不受支持,可以使用顯式實現和方法隱藏來模擬協方差。這是一種在ADO.NET API中徹底使用的模式。

    例如爲:

    public interface ISomeValue { } 
    public abstract class SomeValueBase : ISomeValue { } 
    public class SomeValueImpl : SomeValueBase { } 
    
    public interface ISomeObject { ISomeValue GetValue(); } 
    
    public abstract class SomeObjectBase : ISomeObject 
    { 
        ISomeValue ISomeObject.GetValue() { return GetValue(); } 
        public SomeValueBase GetValue() { return GetValueImpl(); } 
    
        protected abstract SomeValueBase GetValueImpl(); 
    } 
    
    public class SomeObjectImpl : SomeObjectBase 
    { 
        protected override SomeValueBase GetValueImpl() { return GetValue(); } 
        public new SomeValueImpl GetValue() { return null; } 
    } 
    

    通過這樣做,調用GetValue()的最終結果是,它總是會匹配最具體的可用類型。

    +0

    謝謝吉恩解釋我,它可以幫助我:)乾杯 – Learner 2013-03-12 14:10:08

    +0

    非常有幫助的例子,謝謝! – Learner 2015-01-12 16:41:03

    2

    由於這是一個面試問題,您可以運行一下您的答案。

    嚴格地說,具有不同返回類型和相同簽名的方法是不可能的。但是,從廣義上講,實現具體運行時返回類型不同的方法有很多方法。

    一個使用通用參數。另一種方法是返回一個具有多個實現的接口或超類。或者,您可以返回一個可以投射到任何物體的物體。

    正如很多人所提到的,您還可以使用「new」關鍵字在子類中返回相同方法的派生類型。

    +0

    謝謝你gabnaim的答案,這有助於我:) – Learner 2013-03-13 08:43:59

    0

    是的,你可以使用相同的方法,相同的參數(需要自定義)和不同的返回值。

    只要按照下面的代碼,它可能會幫助你。

    public class myClass 
    { 
        public int myReturn() { return 123; } 
        public string myReturn(string temp = null) { return "test"; } 
    } 
    

    的事情是,它需要的參數,使執行的功能,但你仍然可以,因爲你有string temp = null作爲可選參數,這是你還是叫功能帶或不帶參數忽略的參數。

    +0

    我不這麼認爲,它不會編譯「var x = myReturn();」 – 2018-01-24 00:57:07

    0

    我最近有這個確切的問題,因爲我解析了一個配置文件,使用各種類型的全部使用標準的config.Parse(string settingName)類型的接口。

    1解決方案的通用方法:

    T Parse<T> (string settingName) 
    { 
        T Result; 
        doParsing... 
        return T; 
    } 
    

    我真的不喜歡這一點,因爲它涉及到明確指定了所使用的類型,如someSetting = Parse<float>("param");

    所以我使用的溶液是多餘的,但更清潔在我看來:

    T Parse<T> (string settingName, out T result) 
    { 
        doParsing... 
        return T; 
    } 
    

    out變量和返回是相同的所以這是一個有點多餘,但它使我瘦k是一個更簡潔的界面:

    setting = Parse("intparam", out setting); 
    

    ,你會得到返回類型爲冗餘輕微的成本只有變化的方法。最重要的是,如果你的數據類型發生了變化,例如從雙精度到浮點數,那麼你的所有事情都會繼續正常工作,而第一個解決方案最終會得到不能隱式轉換錯誤的結果。

    -1

    你可以做到這一點絲毫接口

    public interface IMyInterface 
    { 
        int Metoda1()enter code here`; 
    } 
    public class MyClass : test.IMyInterface 
    { 
        public IMyInterface Metoda1() 
        { 
         return new MyClas(); 
        } 
        int test.IMyInterface.Metoda1() 
        { 
         return 1; 
        } 
    } 
        static void Main(string[] args) 
        { 
         MyClass instance = new MyClass(); 
         IMyInterface inst = instance.Metoda1(); 
        /* IMyInterface ints2 = inst.Metoda1(); //will not compile*/ 
         Console.WriteLine(inst.GetType().ToString()); ; 
         object inst3 = inst.Metoda1(); 
         Console.WriteLine(inst3.GetType().ToString()); 
        } 
    
    相關問題