ValueTuple covariant คืออะไร


35

สิ่งนี้รวบรวมได้อย่างถูกต้องใน C # 7.3 (Framework 4.8):

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

ฉันรู้ว่านี่คือน้ำตาลประโยคสำหรับต่อไปนี้ซึ่งยังรวบรวมอย่างถูกต้อง:

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

ดังนั้นจึงปรากฏว่า ValueTuples สามารถกำหนดcovariantly , ซึ่งเป็นที่น่ากลัว !

น่าเสียดายที่ฉันไม่เข้าใจว่าทำไม : ฉันรู้สึกว่า C # รองรับความแปรปรวนร่วมบนอินเทอร์เฟซและผู้ได้รับมอบหมายเท่านั้น ValueTypeไม่ใช่

อันที่จริงแล้วเมื่อฉันพยายามทำซ้ำฟีเจอร์นี้ด้วยรหัสของฉันเองฉันล้มเหลว:

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

ดังนั้นทำไมสามารถValueTupleกำหนด covariantly แต่MyValueTuples ไม่สามารถ


2
นี่น่าจะเป็นการดูแลเป็นพิเศษโดยคอมไพเลอร์เช่นเดียวกับวิธีที่คุณสามารถมอบหมายให้nullกับNullable<T>แม้ว่ามันจะเป็นโครงสร้าง
juharr

2
ที่จริงแล้วรหัสที่แปลแล้วมีลักษณะเช่นนี้สำหรับการมอบหมายครั้งที่สอง:ValueTuple<object, string> o = new ValueTuple<object, string>(s.Item1, s.Item2);
Lasse V. Karlsen

2
Tuples แปลกและมีการนำไปใช้อย่างสมบูรณ์ในส่วนหน้าของคอมไพเลอร์ c # แทนที่จะพึ่งพาการแสดง CLR พื้นฐาน ผู้ดำเนินการที่ได้รับมอบหมายนั้นไม่ได้ทำสิ่งที่คุณคิด
Jeremy Lakeman

2
เพิ่มโอเปอเรเตอร์โดยนัยpublic static implicit operator MyValueTuple<A, B>(MyValueTuple<string, string> v) { throw new NotImplementedException(); }เพื่อแยกการกำหนด นอกจากนี้ยังมีคำถามที่ดีโดยวิธี!
Çöđěxěŕ

1
@ Çöđěxěŕบูลส์อาย! ที่ทำให้คอมไพล์ได้และข้อยกเว้นจะถูกโยนตามที่คาดไว้
Mong Zhu

คำตอบ:


25

ฉันเชื่อว่าสิ่งที่เกิดขึ้นจริงที่นี่คือการมอบหมายให้ทำลายล้าง การมอบหมายงาน Tuple จะพยายามแปลงองค์ประกอบโดยปริยายและเป็นไปได้ที่จะมอบหมายstringให้objectนั่นคือสิ่งที่เกิดขึ้นที่นี่

ภาษารองรับการกำหนดค่าระหว่างประเภท tuple ที่มีจำนวนองค์ประกอบเท่ากันโดยที่องค์ประกอบด้านขวามือแต่ละอันสามารถแปลงเป็นองค์ประกอบทางซ้ายมือโดยปริยาย การแปลงอื่น ๆ จะไม่ถือว่าเป็นการมอบหมาย

แหล่ง

ดูได้ที่ sharplab.io


4
ฉันแค่พยายามบน SharpLab นั่นเองค่ะมันไม่ตรงที่
John

3
เพียงเพื่อเสริมว่าในตัวอย่างดั้งเดิมของ OP หากคุณเปลี่ยนsให้พิมพ์(string, object)ส่งผลให้เกิดข้อผิดพลาดในการแปลงแสดงว่ามีการแปลงโดยนัยระหว่างรายการและสตริงสามารถแปลงเป็นสตริงได้โดยปริยาย แต่ไม่ใช่ในทางกลับกัน
Eric Lease
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.