ValueTuple'ı kovaryant yapan nedir?


35

Bu C # 7.3 (Çerçeve 4.8) 'de doğru bir şekilde derler:

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

Bunun aşağıdakiler için sözdizimsel şeker olduğunu biliyorum, bu da doğru bir şekilde derleniyor:

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

Yani, ValueTuples kovaryant olarak atanabilir gibi görünüyor , bu harika !

Ne yazık ki, neden anlamıyorum : C # sadece arayüzler ve delegeler üzerinde kovaryansı desteklediği izlenimi altındaydı . ValueTypeNe de.

Aslında, bu özelliği kendi kodumla çoğaltmaya çalıştığımda başarısız oluyorum:

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>'

Öyleyse, neden ValueTuples kovaryant olarak atanabilir, ancak MyValueTuples olamaz?


2
Bu sadece Atayabileceğiniz nasıl gibi derleyici tarafından olasılıkla özel tedavi olduğu nullbir karşı Nullable<T>bir yapı olmasına rağmen.
juharr

2
Aslında, ayrıştırılmış kod ikinci atama için şöyle görünür:ValueTuple<object, string> o = new ValueTuple<object, string>(s.Item1, s.Item2);
Lasse V. Karlsen

2
Tuples tuhaftır ve altta yatan bir CLR temsiline güvenmek yerine tamamen c # derleyicisi ön ucunda uygulanır. Bu atama operatörü düşündüğünüzü yapmıyor.
Jeremy Lakeman

2
Örtülü bir işleci public static implicit operator MyValueTuple<A, B>(MyValueTuple<string, string> v) { throw new NotImplementedException(); }atamayı yapılandırarak ekleyin . Ayrıca, bu arada harika bir soru!
Çöđěxěŕ

1
@ Çöđěxěŕ boğa gözü! Bu da onu derlenebilir hale getirir ve istisna beklendiği gibi atılır
Mong Zhu

Yanıtlar:


25

Burada olanların yıkıcı bir görev olduğuna inanıyorum. Tuple ataması örtülü bileşenlerini dönüştürmek için çalışacağız ve atamak mümkün olduğu gibi stringhiç object, burada böyle olur.

Dil, her bir sağ taraftaki öğenin örtülü olarak karşılık gelen sol taraftaki öğeye dönüştürülebildiği aynı sayıda öğeye sahip grup türleri arasında atamayı destekler. Diğer dönüşümler ödevler için dikkate alınmaz.

Kaynak

Sharplab.io sitesinde görün


4
Sadece SharpLab üzerinde denedim ve tam olarak bunu yaptığından eminim .
John

3
Eğer değiştirirseniz Sadece OP'ın orijinal örnekte, o güçlendirmek için syazmak için (string, object)bu örtük dönüştürme öğeleri arasında yer alıyor belirten bir dönüşüm hatasına yol açar ve dize örtük dizeye dönüştürülür, ancak bunun tersi olabilir.
Eric Lease
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.