簡體   English   中英

C#中具有相同名稱和簽名但返回類型不同的方法

[英]Method with same name and signature but different return type in C#

我接受了一次采訪,我被問到如下:

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

有人可以告訴我以下內容:

  1. 在任何情況下都是可能的事情(比如基類中的一個和至少派生類中的一個?)如果是這樣的類型是什么? 像編譯或運行時多態?

  2. 在編譯時多態,如果返回類型的方法也與簽名不同怎么辦? 但只有功能名稱相同。 編譯時多態還在嗎?

  3. 在覆蓋中,如果我有不同的返回類型但方法名稱和簽名相同怎么辦? 可能嗎 ? (他問我這個問題,我回答錯誤:()請幫幫我。

謝謝

  • 我假設問題是關於返回類型協方差

    它允許方法返回比在基類型中聲明的類型更多派生的類型,例如

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

    這在Java中受支持,但在C#中不受支持。 由於SomeClass.GetValue的返回類型是string而不是object因此上面不會編譯。

    請注意,您不能僅基於return-type重載方法,即以下內容無效:

     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#中不受支持。

  • 在C#中,你不能有類似的方法

    int Foo() { return 1; }

    void Foo() { return; }

    它們的變化必須超過返回類型。

    如果爭論不同,那么你很高興。

    int Foo(string x) { return 1; }

    void Foo(double x) { return; }

    雖然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()的最終結果是它將始終匹配最具體的可用類型。

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

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

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

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

    一個是使用通用參數。 另一個是返回具有多個實現的接口或超類。 或者,您可以返回一個可以強制轉換為任何對象的對象。

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

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

    只需按照以下代碼,它可能會對您有所幫助。

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

    問題是,它需要參數來執行函數,但是你仍然能夠忽略參數,因為你有string temp = null作為可選參數,你仍然可以調用帶或不帶參數的函數。

    我最近遇到了這個問題,因為我正在解析一個配置文件,其中包含各種類型的配置文件,這些類型都使用標准的config.Parse(string settingName)類型接口。

    第一種解決方案通用方法:

    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變量和返回是相同的,所以它有點多余,但它使我認為是一個更清潔的界面:

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

    並且您獲得的方法僅根據返回類型而有所不同,以獲得輕微的冗余成本。 最重要的是,如果您的數據類型發生變化,例如從double變為float,那么您所有內容都將繼續正常工作,而使用第一個解決方案,您最終得到的不能隱式轉換錯誤。

    您可以使用dynamic返回類型:

    你可以做whit接口

       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());
        }
    

    暫無
    暫無

    聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

     
    粵ICP備18138465號  © 2020-2024 STACKOOM.COM