webentwicklung-frage-antwort-db.com.de

Methode mit demselben Namen und derselben Signatur, aber unterschiedlichem Rückgabetyp in C #

Ich hatte ein Interview, in dem ich folgendes gefragt wurde:

Frage: Eine Methode mit demselben Namen und derselben Signatur, aber unterschiedlichem Rückgabetyp. Ist es möglich und wie heißt dieser Typ, fragte er mich.

Kann mir jemand bitte folgendes sagen:

  1. Ist obiges in jedem Szenario möglich (wie eines in der Basisklasse und eines in einer abgeleiteten Klasse?) Wenn ja, welcher Typ ist es? Wie Kompilierung oder Laufzeitpolymorphismus?

  2. Was ist im Kompilierzeit-Polymorphismus, wenn sich auch die Rückgabetypen mit der Signatur unterscheiden? Aber nur der Name der Funktion ist derselbe. Ist es noch Zeit, den Polymorphismus zu kompilieren?

  3. Was ist beim Überschreiben, wenn ich einen anderen Rückgabetyp habe, der Methodenname und die Signatur jedoch identisch sind? Ist es möglich ? (Er hat mir diese Frage gestellt, ich antwortete wronglY :() Bitte helfen Sie mir.

Vielen Dank

21
Learner
  • Ich gehe davon aus, dass es sich bei der Frage um Rückgabetyp-Kovarianz handelt

    Es ermöglicht einer Methode, einen weiter abgeleiteten Typ als den in einem Basistyp deklarierten zurückzugeben, z.

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

    Dies wird in Java unterstützt, jedoch nicht in C #. Das oben Gesagte wird nicht kompiliert, da der Rückgabetyp von SomeClass.GetValuestring nicht object ist.

    Beachten Sie, dass Sie Methoden, die nur auf dem Rückgabetyp basieren, nicht überladen können, d. H. Folgendes ist nicht gültig:

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

    Sie könnten etwas Ähnliches mit Interfaces machen, obwohl Sie diese explizit implementieren müssten, um zu disambiguieren:

    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; }
    }
    
  • Wenn die Namen identisch sind, die Parameter jedoch unterschiedlich sind, handelt es sich um eine Methodenüberladung. Dies ist eine Form des Polymorphismus (Ad-hoc-Polymorphismus). Überladungen werden beim Kompilieren statisch aufgelöst (es sei denn, Sie verwenden dynamic. In diesem Fall werden sie auf die Laufzeit verschoben).

    Sie können sowohl die Anzahl der Parameter als auch deren Typ überladen, sodass alle folgenden Werte gültig sind:

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

    Beachten Sie, dass Sie den Rückgabetyp dieser Methoden variieren können - Methoden können nicht nur allein aufgrund ihres Rückgabetyps überladen werden, sondern sie können sich auch unterscheiden, wenn ihre Parameterlisten unterschiedlich sind.

  • Dies ist wiederum eine Kovarianz vom Rückgabetyp und wird in C # nicht unterstützt.

  • 32
    Lee

    In C # können Sie keine Methoden wie haben

    int Foo() { return 1; }

    void Foo() { return; }

    Sie müssen um mehr als den Rückgabetyp variieren.

    Wenn die Argumente unterschiedlich sind, können Sie loslegen.

    int Foo(string x) { return 1; }

    void Foo(double x) { return; }

    10
    Todd Sprang

    Obwohl Rückgabekovarianz in C # nicht unterstützt wird, ist es möglich, sie mithilfe der expliziten Implementierung und dem Ausblenden von Methoden zu emulieren. Dies ist ein Muster, das in den ADO.NET-APIs sorgfältig verwendet wird.

    Z.B.:

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

    Auf diese Weise ergibt das Nettoergebnis des Aufrufs von GetValue(), dass immer der spezifischste verfügbare Typ angegeben wird.

    7
    Jean Hominal

    Ja, es ist möglich, mehrere Methoden mit derselben Signatur, aber unterschiedlichen Rückgabetypen zu verwenden, wobei die explizite Schnittstellenimplementierung wie folgt verwendet wird:

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

    Da dies eine Interviewfrage ist, können Sie Ihre Antwort etwas ausführen.

    Streng genommen ist eine Methode mit einem anderen Rückgabetyp und derselben Signatur nicht möglich. Im Großen und Ganzen gibt es jedoch viele Möglichkeiten, eine Methode zu implementieren, deren konkreter Typ für die Laufzeit unterschiedlich ist.

    Einer verwendet generische Parameter. Eine andere ist die Rückgabe einer Schnittstelle oder einer Superklasse mit mehreren Implementierungen. Oder Sie können ein Objekt zurückgeben, das zu einem beliebigen Objekt umgewandelt werden kann.

    Wie bereits erwähnt, können Sie auch das Schlüsselwort "new" verwenden, um einen abgeleiteten Typ derselben Methode in einer Unterklasse zurückzugeben. 

    2
    gabnaim
    0
    Thomas

    Ich hatte vor kurzem genau dieses Problem, seit ich eine Konfigurationsdatei mit verschiedenen Typen parsen wollte, die alle eine standardmäßige Schnittstelle vom Typ config.Parse (string settingName) verwenden.

    Erste generische Lösungsmethode:

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

    Ich mochte das nicht wirklich, da es explizit darauf ankam, welchen Typ es verwendet, wie someSetting = Parse<float>("param");.

    Die Lösung, die ich verwendete, ist redundant, aber meiner Meinung nach viel sauberer:

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

    Die Ausgangsvariable und die Rückgabe sind identisch, daher ist sie ein wenig redundant, ermöglicht jedoch ein meiner Meinung nach wesentlich saubereres Interface:

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

    Und Sie erhalten Methoden, die sich nur durch den Rückgabetyp unterscheiden, was zu geringen Redundanzkosten führt. Wenn sich der Typ Ihrer Daten ändert, zum Beispiel von einem Double in einen Float, funktioniert alles weiterhin einwandfrei, wohingegen Sie mit der ersten Lösung am Ende keine Fehler implizit konvertieren können.

    0
    Russell Bearden

    ja, Sie können dieselbe Methode, dieselben Parameter (müssen angepasst werden) und unterschiedliche Rückgabewerte verwenden.

    Folgen Sie einfach den untenstehenden Codes, es könnte Ihnen helfen.

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

    die Sache ist, es braucht Parameter, um die Funktionen ausführen zu lassen, aber Sie können die Parameter trotzdem ignorieren, da Sie string temp = null als optionale Parameter haben, dh, Sie rufen die Funktionen immer noch mit oder ohne Parameter auf.

    0
    Marhazk