A cosa servono i tipi di restituzione covarianti?

6

In questo articolo , è scritto che in C # 8.0 new la funzionalità di tipo di ritorno di tipo convociativo sarà inclusa poiché la community richiede questa funzione per un periodo di tempo molto lungo.

Qualcuno può spiegare perché e quando questa funzione è richiesta con un esempio pratico?

    
posta Himanshu Mange 05.04.2018 - 11:01
fonte

3 risposte

6

In primo luogo, vale la pena notare che l'articolo è molto probabilmente sbagliato. Attualmente esiste una lunga lista di funzionalità ufficialmente assegnate per C # 8.0 , ma i tipi di ritorno covarianti non sono tra questi. Quella funzione è programmata per X.0 , ovvero deve apparire in una versione principale, quindi potrebbe vengono visualizzati per 8.0 (ma ciò è incredibilmente improbabile), più probabile sarà in 9.0 o 10.0 ecc.

Per quanto riguarda l'utilizzo della funzione, ha letto il problema originale di Roslyn di tre anni fa . Ha numerosi usi riguardo alla possibilità di restringere il tipo restituito all'interno dei metodi in tipi derivati, ad esempio un'implementazione di un'interfaccia factory potrebbe specificare che restituisce un tipo concreto, piuttosto che un'interfaccia.

Ad esempio, utilizzando i generici, possiamo fare qualcosa di simile:

public interface IFactory<T>
{
    T Create();
}

public class Foo{}

public class FooFactory : IFactory<Foo>
{
    public Foo Create() => null;
}

Ma se IFactory utilizza invece ulteriori interfacce per le sue astrazioni, piuttosto che i generici, il codice simile non è attualmente possibile:

public interface IFoo {}

public interface IFactory
{
    IFoo Create();
}

public class Foo : IFoo {}

public class FooFactory : IFactory
{
    public Foo Create() => null; // Compiler complains at Foo; wants IFoo
}

Tale codice diventerebbe legale con i tipi di ritorno covarianti.

    
risposta data 05.04.2018 - 11:31
fonte
3

Tipi di restituzione covarianti indicano che un metodo di sovrascrittura può specificare un tipo di ritorno più specifico rispetto al metodo di base. Eg.

class WebRequest {
    virtual WebRequest Create() { ... }
}

class HttpWebRequest : WebRequest {
    override HttpWebRequest Create() { ... }
}

Attualmente (senza tipi di ritorno covarianti) il metodo sovrascritto deve specificare esattamente lo stesso tipo di ritorno, WebRequest , e dovrai eseguire manualmente il cast del valore di ritorno su HttpWebRequest , che è brutto.

    
risposta data 05.04.2018 - 11:55
fonte
3

(Ci scusiamo prima, con C # è un po 'arrugginito)

Come menzionato nelle altre risposte, la grande caratteristica dei tipi di ritorno convenzionali è la possibilità di sostituire le funzioni virtuali con funzioni che restituiscono un tipo di ritorno più specifico.

Ad esempio:

public class Foo
{
    virtual public Foo getCopy(); { //Create a copy of this Foo and return it }
}

Il metodo getCopy() restituisce una copia del Foo su cui è stato invocato, finora, così buono. Aggiungiamo una classe che eredita da Foo .

public class Bar : Foo
{
    override public Foo getCopy(); { //Create a copy of this Bar and return it as a Foo }
}

Notare che senza tipi di ritorno covarianti dobbiamo dichiarare che restituiamo un Foo (ufficialmente) invece di un Bar (anche se in realtà restituiamo un Bar ). Questo potrebbe non essere così male finché non scrivi il codice seguente.

//Copying things
Foo myFoo;
Foo myOtherFoo = myFoo.getCopy();

Bar myBar;
Bar myOtherBar = myBar.getCopy(); //Compiler error - getCopy() returns a Foo

Anche se sai che myBar è un Bar , e che (in realtà) ottieni un Bar dal getCopy() di myBars, devi eseguire il cast del valore restituito per farlo compilare. Peggio ancora, è una potenziale fonte di bug ...

public class Baz : Foo
{
    override public Foo getCopy(); { //Create a copy of this Baz and return it as a Foo }
}

//Copying more things
Foo myFoo;
Foo myOtherFoo = myFoo.getCopy();

Bar myBar;
Bar myOtherBar = myBar.getCopy() as Bar;

Baz myBaz;
Baz myOtherBaz = myBar.getCopy() as Baz; //Whoops

Hai notato l'errore? Senza valori di ritorno covarianti si potrebbe notare solo durante il runtime (quando il programma si blocca), con loro il compilatore può dirti in fase di compilazione: No, non può funzionare.

In sintesi: i valori di restituzione covarianti ti consentono di scrivere un codice più breve, più preciso e più sicuro.

    
risposta data 05.04.2018 - 14:13
fonte

Leggi altre domande sui tag