2013-03-12 18 views
18

ho avuto un colloquio in cui mi è stato chiesto quanto segue:metodo con lo stesso nome e la firma, ma tipo di ritorno in C#

Domanda: un metodo con lo stesso nome e la firma, ma diverso tipo di ritorno. È possibile e come si chiama questo mi ha chiesto.

Qualcuno può dirmi il seguente:

  1. è una cosa sopra possibile in ogni scenario (come uno in classe di base e uno in atleast classe derivata?) In caso affermativo che tipo è? Come il polimorfismo di compilazione o runtime?

  2. In polimorfismo in fase di compilazione, cosa succede se i tipi di restituzione dei metodi sono anche diversi insieme alla firma? Ma solo il nome della funzione è lo stesso. È ancora il polimorfismo del tempo di compilazione?

  3. In caso di override, cosa succede se ho un tipo di ritorno diverso ma il nome del metodo e la firma sono gli stessi? È possibile ? (Mi ha chiesto questa domanda, ho risposto a torto :() Ti prego, aiutami.

Grazie

+7

Qual è stata la risposta al tuo avvenire, e perché? – Oded

+3

Non è possibile. Puoi provare a sovraccaricare i tuoi metodi in quel modo, ma il compilatore non lo accetterà. – Nolonar

+0

@Oded: lol Ho appena realizzato che ho risposto in modo errato. Ho detto che il suo polimorfismo compiletime chiamato e all'interno della stessa classe non è possibile, ma una funzione virtuale può essere in classe base e possiamo sovrascriverla o utilizzare la parola chiave "nuova" nella classe derivata con un tipo di ritorno differente. Ma se lo abbiamo nella stessa classe, darà un errore dicendo che due funzioni hanno lo stesso nome. Non ero pensieroso e attento durante l'intervista, mi sono appena reso conto :(lol questa semplice domanda non potrei rispondere, andato. Dovrei lavorare su questo più. – Learner

risposta

30

  • presumo la questione è di circa return type covariance

    Consente un metodo per restituire un altro tipo -derived di quello dichiarato in un tipo di base per esempio

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

    Questo è supportato in Java, ma non in C#. è possibile che questo non verrà compilato sinc e il tipo di reso di SomeClass.GetValue è string non object.

    Nota che non si può sovraccaricare metodi basati sulla sola ritorno di tipo vale a dire la seguente non è valido:

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

    Si potrebbe fare qualcosa di simile utilizzando le interfacce anche se avrebbe bisogno di attuarle in modo esplicito per disambiguare:

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

  • Se i nomi sono gli stessi ma i parametri sono diversi, questo è il sovraccarico del metodo. Questa è una forma di polimorfismo (polimorfismo ad-hoc). I sovraccarichi vengono risolti staticamente in fase di compilazione (a meno che non si stia utilizzando dynamic nel qual caso vengono posticipati al tempo di esecuzione).

    È possibile sovraccaricare sia sul numero di parametri e il loro tipo, in modo da seguenti sono tutti validi:

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

    noti che è possibile variare il tipo di ritorno di questi metodi - metodi non possono essere sovraccaricati solo sulla base di il loro tipo di ritorno da solo, ma possono differire se i loro elenchi di parametri sono diversi.

  • Ancora una volta questo è il tipo di ritorno di covarianza e non è supportato in C#.

  • +0

    grazie, ma nella seconda domanda, sono curioso di sapere, quando diciamo che un metodo sta sovraccaricando. Ad esempio, dovremmo avere lo stesso nome per il metodo prima? Secondo, dovremmo variare il parametro per numero o tipo? E infine dovrei avere lo stesso tipo di ritorno giusto? Altrimenti il ​​programma non verrà compilato affatto, è questo che intendi? E nessun concetto in C# è lì in questo giusto? – Learner

    +0

    @Divine - Quando si sovraccaricano i nomi dei metodi devono essere uguali, ma gli elenchi dei parametri devono essere diversi. Possono differire nei tipi e/o nel numero di parametri. Non è necessario avere lo stesso tipo di ritorno, è solo che la risoluzione di sovraccarico viene eseguita solo sui parametri di un metodo, non sul tipo di ritorno. Ciò significa che i metodi non possono essere sovraccaricati sul solo tipo di ritorno. Ho aggiornato la risposta con questa informazione. C# consente l'overloading del metodo, ma non consente il sovraccarico dei metodi in base al tipo restituito e non consente la covarianza di tipo restituito. – Lee

    +0

    Grazie mille, come ha detto Todd, public int DoSomething (valore stringa) {} public void DoSomething (int value, string value) {} Posso avere ragione? Nessun problema ? Comunque capisco che non sovraccarichi – Learner

    10

    In C#, non si può avere metodi come

    int Foo() { return 1; }

    void Foo() { return; }

    Essi devono variare di oltre il tipo di ritorno.

    Se gli argomenti sono diversi, allora sei a posto.

    int Foo(string x) { return 1; }

    void Foo(double x) { return; }

    +0

    Questo mi fa capire perfettamente, grazie mille :) Ciao – Learner

    +0

    BTW, non vedo il polimorfismo qui, ma non mi sono seduto nella tua intervista. :) Real quick, polymorphism sarebbe come void Foo (Animal a) {..} e class Dog: Animal {}. Fai la chiamata Foo (aDog) con un cane non un animale.Polymorphism esegue la conversione magica dal tipo derivato (Cane) al tipo di base (Animale). Maggiori informazioni sul polimorfismo qui: http://www.codeproject.com/Articles/4839/Building-Snap-In-Applications –

    +0

    Grazie ancora Todd, in qualche modo molte cose mi sembrano nuove perché non ho avuto il tatto per 3 mesi ora Ancora una volta sono un principiante (ho circa 2 anni di esperienza, ho ancora molto da imparare) ... grazie :) Sto passando questo link codeproject :) Saluti – Learner

    5

    Sì, è possibile avere più metodi con la stessa firma, ma diversi tipi di rendimento, con esplicita implementazione dell'interfaccia come mostrato di seguito:

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

    Grazie Pieter :) È una buona informazione per me :) Cheers – Learner

    6

    Sebbene tipo di ritorno la covarianza non è supportata in C#, è possibile emularla usando l'implementazione esplicita e l'occultamento del metodo. Questo è un modello che viene utilizzato completamente nelle API ADO.NET.

    Es .:

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

    Così facendo, il risultato netto di chiamare GetValue() è che sarà sempre corrispondere al tipo di disposizione più specifica.

    +0

    Grazie Jean per avermi spiegato, mi aiuta :) Saluti – Learner

    +0

    Un esempio molto utile, grazie! – Learner

    2

    Poiché si tratta di una domanda di intervista, è possibile eseguire un po 'la risposta.

    In senso stretto, un metodo con tipo di restituzione diverso e la stessa firma non è possibile. Tuttavia, in generale, ci sono molti modi per implementare un metodo il cui tipo di ritorno del tempo di esecuzione concreto varia.

    Uno sta utilizzando parametri generici. Un altro sta restituendo un'interfaccia o una super classe con più implementazioni. Oppure puoi restituire un oggetto, che può essere lanciato su qualsiasi cosa.

    Come già detto, è anche possibile utilizzare la parola chiave "new" per restituire un tipo derivato dello stesso metodo in una sottoclasse.

    +0

    Grazie gabnaim per la risposta, che mi aiuta :) – Learner

    0

    sì, è possibile utilizzare lo stesso metodo, gli stessi parametri (è necessario personalizzare) e valori di ritorno diversi.

    Basta seguire i codici di seguito, potrebbe aiutarti.

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

    la cosa è, richiede il parametro di fare eseguire le funzioni, ma è ancora in grado di ignorare i parametri poiché avete string temp = null parametri come optional, che è ancora chiamare le funzioni, con o senza i parametri.

    +0

    Non penso, non verrà compilato con "var x = myReturn();" –

    0

    Recentemente ho avuto questo problema esatto poiché stavo analizzando un file di configurazione con vari tipi che utilizzano tutti un tipo standard di interfaccia di tipo config.Parse (string settingName).

    1 ° Soluzione metodo generico:

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

    ho fatto non piace molto questo dato che ha coinvolto in modo esplicito specificando il tipo che viene utilizzato come someSetting = Parse<float>("param");

    Quindi la soluzione che ho usato è ridondante, ma molto di più pulita a mio parere:

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

    la variabile fuori e il ritorno sono identici, quindi è un po 'ridondante, ma quello che mi permette sottile k è un'interfaccia molto più pulito:

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

    e si ottiene metodi che variano solo dal tipo di ritorno per un leggero costo di ridondanza. Inoltre, se il tipo di dati cambia, ad esempio da un doppio a un float, tutto continuerà a funzionare correttamente, mentre con la prima soluzione che si otterrebbe non è possibile convertire implicitamente errori.

    -1

    si può fare briciolo interfaccia

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