Cosa rende ValueTuple covariante?


35

Questo viene compilato correttamente in C # 7.3 (Framework 4.8):

(string, string) s = ("a", "b");
(object, string) o = s;

So che questo è lo zucchero sintattico per quanto segue, che si compila anche correttamente:

ValueTuple<string, string> s = new ValueTuple<string, string>("a", "b");
ValueTuple<object, string> o = s;

Quindi, sembra che ValueTuples possa essere assegnato in modo covariante , il che è fantastico !

Sfortunatamente, non capisco perché : avevo l'impressione che C # supportasse solo la covarianza su interfacce e delegati . ValueTypenon è nessuno dei due.

In effetti, quando provo a duplicare questa funzione con il mio codice, non riesco:

struct MyValueTuple<A, B>
{
    public A Item1;
    public B Item2;

    public MyValueTuple(A item1, B item2)
    {
        Item1 = item1;
        Item2 = item2;
    }
}

...

MyValueTuple<string, string> s = new MyValueTuple<string, string>("a", "b");
MyValueTuple<object, string> o = s;
// ^ Cannot implicitly convert type 'MyValueTuple<string, string>' to 'MyValueTuple<object, string>'

Quindi, perché può ValueTupleessere assegnato in modo covariante, ma MyValueTupleno?


2
Questo è probabilmente un trattamento speciale da parte del compilatore, proprio come è possibile assegnare nulla un Nullable<T>sebbene sia una struttura.
juharr

2
In realtà, il codice decompilato appare così per il secondo incarico:ValueTuple<object, string> o = new ValueTuple<object, string>(s.Item1, s.Item2);
Lasse V. Karlsen,

2
Le tuple sono strane e sono implementate interamente nel front-end del compilatore c #, invece di fare affidamento su una rappresentazione CLR sottostante. Quell'operatore di assegnazione non sta facendo ciò che pensi.
Jeremy Lakeman,

2
Aggiungi un operatore implicito alla public static implicit operator MyValueTuple<A, B>(MyValueTuple<string, string> v) { throw new NotImplementedException(); }sua decostruzione del compito. Inoltre, ottima domanda a proposito!
Çöđěxěà,

1
@ Çöđěxěà occhio di tori! questo lo rende compilabile e l'eccezione viene generata come previsto
Mong Zhu,

Risposte:


25

Credo che ciò che sta realmente accadendo qui sia un compito distruttivo. Assegnazione tuple cercherà di convertire in modo implicito le sue componenti, e come è possibile assegnare stringa object, che è ciò che accade qui.

Il linguaggio supporta l'assegnazione tra tipi di tupla che hanno lo stesso numero di elementi, in cui ciascun elemento del lato destro può essere implicitamente convertito nel corrispondente elemento del lato sinistro. Altre conversioni non vengono prese in considerazione per i compiti.

fonte

Guardalo su sharplab.io


4
L'ho appena provato su SharpLab e sicuramente fa esattamente questo .
Giovanni

3
Solo per rinforzare questo, nell'esempio originale di OP, se si cambia sper digitare (string, object)si traduce in un errore di conversione, indicando che la conversione implicita sta avvenendo tra gli elementi e che la stringa può essere implicitamente convertita in stringa, ma non viceversa.
Eric Lease,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.