web-dev-qa-db-fra.com

Méthode avec le même nom et la même signature mais avec un type de retour différent en C #

J'ai eu une interview où on m'a demandé ce qui suit:

Question: Une méthode avec le même nom et la même signature mais avec un type de retour différent. Est-ce possible et comment s'appelle ce type qu'il m'a demandé.

Quelqu'un peut-il s'il vous plaît me dire ce qui suit:

  1. Ce qui précède est-il possible dans tous les scénarios (comme un dans la classe de base et un dans la classe dérivée au moins?) Si tel est le type Vous aimez compiler ou exécuter un polymorphisme?

  2. Dans le polymorphisme à la compilation, que se passe-t-il si les types de méthode de retour sont également différents de la signature? Mais seul le nom de la fonction est identique. Est-ce encore le polymorphisme de compilation?

  3. En cas de remplacement, que se passe-t-il si le type de retour est différent mais que le nom de la méthode et la signature sont identiques? C'est possible ? (Il m'a posé cette question, j'ai répondu à tort :() Aidez-moi s'il vous plaît.

Je vous remercie

21
Learner
  • Je suppose que la question concerne covariance du type de retour

    Il permet à une méthode de renvoyer un type plus dérivé que celui déclaré dans un type de base, par ex.

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

    Ceci est supporté dans Java mais pas en C #. Ce qui précède ne sera pas compilé car le type de retour de SomeClass.GetValue est string pas object.

    Notez que vous ne pouvez pas surcharger les méthodes basées sur le type de retour seul, c’est-à-dire que ce qui suit n’est pas valide:

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

    Vous pouvez faire quelque chose de similaire en utilisant des interfaces bien que vous ayez besoin de les implémenter explicitement pour être sans ambiguïté:

    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; }
    }
    
  • Si les noms sont identiques mais que les paramètres sont différents, il s'agit d'une surcharge de méthode. C'est une forme de polymorphisme (polymorphisme ad hoc). Les surcharges sont résolues statiquement au type de compilation (sauf si vous utilisez dynamic, auquel cas elles sont reportées à l'exécution).

    Vous pouvez surcharger le nombre de paramètres et leur type. Les éléments suivants sont donc valides:

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

    Notez que vous pouvez modifier le type de retour de ces méthodes - les méthodes ne peuvent être surchargées qu'en fonction de leur type de retour mais elles peuvent être différentes si leurs listes de paramètres sont différentes.

  • Là encore, il s'agit d'une covariance de type de retour qui n'est pas prise en charge en C #.

  • 32
    Lee

    En C #, vous ne pouvez pas avoir de méthodes comme

    int Foo() { return 1; }

    void Foo() { return; }

    Ils doivent varier selon le type de retour.

    Si les arguments sont différents, alors vous êtes prêt à partir.

    int Foo(string x) { return 1; }

    void Foo(double x) { return; }

    10
    Todd Sprang

    Bien que la covariance du type de retour ne soit pas prise en charge en C #, il est possible de l'émuler à l'aide d'une implémentation explicite et du masquage de méthode. C'est un modèle qui est utilisé à fond dans les API ADO.NET.

    Par exemple.:

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

    En faisant cela, le résultat net de l'appel de GetValue() est qu'il correspondra toujours au type disponible le plus spécifique.

    7
    Jean Hominal

    Oui, il est possible d’avoir plusieurs méthodes avec la même signature, mais différents types de retour, en utilisant Implicit Interface Implementation comme indiqué ici:

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

    Comme il s’agit d’une question d’entrevue, vous pouvez lire un peu votre réponse.

    Strictement parlant, une méthode avec un type de retour différent et la même signature n'est pas possible. Cependant, de manière générale, il existe de nombreuses façons de mettre en œuvre une méthode dont le type de retour de temps d'exécution concret varie.

    On utilise des paramètres génériques. Un autre retourne une interface ou une super classe avec plusieurs implémentations. Ou, vous pouvez retourner un objet, qui peut être converti en n'importe quoi.

    Comme beaucoup l'ont mentionné, vous pouvez également utiliser le mot clé "new" pour renvoyer un type dérivé de la même méthode dans une sous-classe. 

    2
    gabnaim
    0
    Thomas

    J'ai récemment eu ce problème exact car j'analysais un fichier de configuration avec différents types qui utilisaient tous une sorte standard d'interface de type config.Parse (string settingName).

    Méthode générique de la 1ère solution:

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

    Je n’aimais pas vraiment cela car cela impliquait de spécifier explicitement le type utilisé tel que someSetting = Parse<float>("param");

    Donc, la solution que j'ai utilisée est redondante mais beaucoup plus propre à mon avis:

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

    La variable out et le retour sont identiques, donc c'est un peu redondant mais cela permet une interface beaucoup plus propre à mon avis:

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

    Et vous obtenez des méthodes qui ne varient que par type de retour pour un léger coût de redondance. En plus de cela, si le type de vos données change, par exemple d'un double à un flottant, tout continuera à fonctionner correctement, alors qu'avec la première solution que vous obtiendrez, vous ne pourrez pas convertir implicitement les erreurs.

    0
    Russell Bearden

    oui, vous pouvez utiliser la même méthode, les mêmes paramètres (besoin de personnalisation) et différentes valeurs de retour.

    Il suffit de suivre les codes ci-dessous, cela pourrait vous aider.

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

    le fait est que cela nécessite un paramètre pour que les fonctions soient exécutées, mais vous pouvez toujours ignorer les paramètres puisque vous avez string temp = null comme paramètres facultatifs, ce qui signifie que vous appelez toujours les fonctions avec ou sans les paramètres.

    0
    Marhazk