26

以下のようなことを聞​​かれたインタビューを受けました。

質問: 名前とシグネチャが同じで、戻り値の型が異なるメソッド。それは可能ですか、そして彼は私に尋ねました。

誰か次のことを教えてください。

  1. 上記のことはどのシナリオでも可能ですか (少なくとも基本クラスのシナリオと派生クラスのシナリオのように?) もしそうなら、それはどのタイプですか? コンパイルや実行時のポリモーフィズムのように?

  2. コンパイル時のポリモーフィズムで、メソッドの戻り値の型も署名とともに異なる場合はどうなりますか? ただし、関数の名前だけは同じです。まだコンパイル時のポリモーフィズムですか?

  3. オーバーライドで、戻り値の型が異なるがメソッド名とシグネチャが同じ場合はどうなりますか? 出来ますか ?(彼は私にこの質問をしました、私は間違って答えました:() 助けてください。

ありがとうございました

4

9 に答える 9

41

  • 質問は戻り値の型の共分散に関するものだと思います

    これにより、メソッドは、基本型で宣言されたものよりも派生した型を返すことができます。

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

    これは Java ではサポートされていますが、C# ではサポートされていません。SomeClass.GetValueの戻り値の型がis stringnotであるため、上記はコンパイルされません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; }
    }
    

  • 名前は同じでもパラメーターが異なる場合、これはメソッドのオーバーロードです。これは一種のポリモーフィズム (アドホック ポリモーフィズム) です。オーバーロードは、コンパイル タイプで静的に解決されます (使用dynamicしている場合を除き、実行時に延期されます)。

    パラメータの数とその型の両方をオーバーロードできるため、以下はすべて有効です。

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

    これらのメソッドの戻り値の型は変更できることに注意してください。メソッドは、戻り値の型のみに基づいてオーバーロードすることはできませんが、パラメーター リストが異なる場合は異なる可能性があります。

  • 繰り返しますが、これは戻り型の共分散であり、C# ではサポートされていません。

  • 于 2013-03-12T13:28:49.510 に答える
    13

    C# では、次のようなメソッドを持つことはできません。

    int Foo() { return 1; }

    void Foo() { return; }

    戻り値の型以上に異なる必要があります。

    引数が異なる場合は、問題ありません。

    int Foo(string x) { return 1; }

    void Foo(double x) { return; }

    于 2013-03-12T13:33:11.757 に答える
    7

    戻り値の型の共分散は 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()常に最も具体的な利用可能な型と一致することになります。

    于 2013-03-12T13:43:22.637 に答える
    6

    はい、次に示すように、明示的なインターフェイスの実装を使用して、同じ署名で異なる戻り型を持つ複数のメソッドを持つことができます。

    public interface I {
      int foo();
    }
    
    public class C : I {
      double foo() { return 2.0; }
      int I.foo() { return 4; }
    }
    
    于 2013-03-12T13:42:19.013 に答える
    2

    これはインタビューの質問なので、あなたの答えを少し実行することができます.

    厳密に言えば、戻り値の型が異なり、シグネチャが同じメソッドは使用できません。ただし、大まかに言えば、実行時の具体的な戻り値の型が異なるメソッドを実装する方法は多数あります。

    1 つは、ジェネリック パラメーターを使用することです。もう 1 つは、複数の実装を持つインターフェイスまたはスーパー クラスを返すことです。または、何にでもキャストできるオブジェクトを返すこともできます。

    多くの人が言及したように、「new」キーワードを使用して、サブクラスで同じメソッドの派生型を返すこともできます。

    于 2013-03-12T13:59:46.833 に答える
    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 変数と return は同一であるため、少し冗長ですが、よりクリーンなインターフェイスと思われるものを有効にします。

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

    また、冗長性のわずかなコストで、戻り値の型だけが異なるメソッドを取得できます。その上、データの型が変更された場合、たとえば double から float に変更された場合、すべてが正常に機能し続けますが、最終的に得られる最初のソリューションでは暗黙的にエラーを変換することはできません。

    于 2014-05-29T07:53:52.933 に答える
    -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());
        }
    
    于 2015-11-12T23:48:04.003 に答える