เมื่อใดจะดีกว่าที่จะใช้ Tuple กับ KeyValuePair


91

โดยทั่วไปฉันจะใช้KeyValuePair<TKey,TValue>ประเภทเมื่อใดก็ตามที่ฉันมีข้อมูลที่เกี่ยวข้องกับคู่ในแง่ที่ว่าหนึ่งเป็นกุญแจสำคัญ หากข้อมูลไม่เกี่ยวข้องกันTuple<T1,T2>ประเภทนั้นก็สมเหตุสมผลกว่าและฉันจะไปด้วย

ตอนนี้ฉันเพิ่งอ่านบทความนี้เกี่ยวกับสาเหตุที่จะหลีกเลี่ยงการทั่วไปและชอบKeyValuePair<TKey,TValue> อาร์กิวเมนต์หลักเป็นผลประโยชน์ของTuple<T1,T2>Tuple<T1,T2>

ประสิทธิภาพภายนอกมีเหตุผลใดที่ KVP จะเป็นทางเลือกที่ดีกว่า a Tuple<T1,T2>?


4
A KeyValuePairคือคีย์และค่า a Tuple<T1,T2>เป็นเพียงคู่ของค่าที่เท่ากัน คุณยังสามารถถามว่า: "ทำไมฉันจึงควรใช้ a List<Class>if i can use Dictionary<A,B>"
Tim Schmelter

4
ถูกต้อง แต่ในกรณีนั้นคุณสามารถใช้คีย์เพื่อค้นหาข้อมูลได้ มันหมายถึงอะไรบางอย่าง ในกรณีนี้ชื่อเป็นเพียงความหมาย แต่ไม่มีความหมายอะไรเลย (สำหรับโปรเซสเซอร์)
Nick Gotch

1
ทูเปิลไม่ใช่คู่ที่มีค่าเท่ากัน แต่มีจำนวนประเภทเท่ากัน บางทีนี่อาจถูกมองว่าเป็นการ nitpicking แต่เช่น C มีการสร้างยูเนี่ยนสำหรับการแทนค่าที่ต่างกัน :)
Jonas

คำตอบ:


68

ประเภทอาจได้รับการพิจารณาชื่อที่ไม่ดีสำหรับหนึ่ง KeyValuePair ตามชื่อควรแทนคีย์และค่า จะเกิดอะไรขึ้นถ้าวัตถุทั้งสองของคุณไม่ใช่กุญแจและค่าเพียงสองสิ่ง? ถ้าฉันเห็นเมธอดหรือคุณสมบัติที่มีประเภทKeyValuePair<TKey, TValue>ฉันคาดหวังว่าค่าของ KVP จะเป็นคีย์และค่า นี่เป็นเพียงเรื่องของการสื่อสารความตั้งใจและทำให้ชัดเจนกับตัวเองในอนาคตหรืออาจเป็นสมาชิกในทีมคนอื่น ๆ ทูเปิลไม่ได้บ่งบอกถึงความสัมพันธ์แบบนั้น

Tuples ยังช่วยให้เพิ่มค่าอื่นได้ง่ายขึ้นทำให้เป็น 3-tuple (หรือ triplet แล้วแต่คุณต้องการเรียก) NET บางภาษาเช่น F # มีไวยากรณ์พิเศษรอบทูเปิลด้วย

สำหรับมุมมองของการนำไปใช้งานTupleหลายสิ่งKeyValuePairไม่ สิ่งเหล่านี้เปรียบได้กับการใช้งานIComparableและIStructuralEquatableอินเทอร์เฟซดังนั้นจึงทำให้ง่ายต่อการเปรียบเทียบสิ่งสองสิ่ง


1
ฉันพบวิธีที่ยากที่คุณสามารถใส่ KeyValuePairs ลงในพจนานุกรม แต่จะไม่ได้ผลลัพธ์กลับมา
MKesper

3
นอกจากนี้ C # 7.0 ใหม่ยังรองรับไวยากรณ์ใหม่สำหรับทูเปิลซึ่งทำให้ง่ายขึ้นและทำงานได้ดีกว่า KeyValuePairs visualstudiomagazine.com/articles/2017/01/01/…
Jacob Stamm

1
นอกจากนี้ความสามารถในการตั้งชื่อพารามิเตอร์ในสิ่งที่สองทำให้ผู้บริโภคเข้าใจได้ง่ายขึ้นว่าพวกเขาควรจะใช้เพื่ออะไร ในแบบทั่วไปเช่น KVP เป็นเรื่องที่ทุกคนคาดเดาได้เว้นแต่จะมีการบันทึกไว้เป็นพิเศษ - สิ่งที่ควรจะเป็น "คีย์" คือไม่ใช่ประเภท แต่เป็นสิ่งที่อยู่ในโลกแห่งความเป็นจริงเช่นชื่อการตั้งค่าโซเชียล หมายเลขความปลอดภัย ฯลฯ
rory.ap

40

KeyValuePairเป็นโครงสร้างและTupleเป็นคลาส

นั่นคือความแตกต่างหลักที่มีผลต่อวิธีการคัดลอกวัตถุไม่ว่าจะโดยการอ้างอิงหรือค่าต่างๆ

และด้วยเหตุนี้Tuple<T1,T2>เมื่อส่งผ่านไปรอบ ๆ ก็ใช้ "4byte" ในระบบปฏิบัติการ 32 บิตในขณะที่KeyValuePair<K,V>ต้องใช้ "K และ V" มากกว่า

อย่างไรก็ตามการเปรียบเทียบ Tuple และ KeyValuePair ไม่ใช่ความคิดที่ดี (ไม่สมเหตุสมผลสำหรับฉัน) เนื่องจากทั้งสองมีจุดประสงค์ที่แตกต่างกัน


3
พวกเขาตอบสนองวัตถุประสงค์ที่แตกต่างกันอย่างไร? คุณช่วยอธิบายให้ละเอียดได้ไหม
OldSchool

2
@YakRangi keyvaluepair มีไว้เพื่อใช้เป็นที่เก็บคีย์และค่าในพจนานุกรมไม่เช่นนั้นก็ไม่มีจุดประสงค์ใด ๆ ในทางกลับกัน Tuple สามารถใช้เพื่อจัดเก็บสมาชิกที่เกี่ยวข้องกันโดยพลการ นอกจากนี้ด้วย Tuple คุณสามารถจัดเก็บสมาชิกหลายคนรวมกันไม่ใช่แค่ 2
Sriram Sakthivel

1
@SriramSakthivel ซึ่งหมายความว่าคำตอบสำหรับคำถาม OP คืออย่าใช้ KVP เว้นแต่คุณจะเรียกดูพจนานุกรม
Alex Fainshtein

24

แม้จะมีความหมาย แต่ประสิทธิภาพอาจเป็นข้อพิจารณาที่สำคัญเมื่อคุณพิจารณาทั้งสองตัวเลือก ดังที่ได้กล่าวไว้ก่อนหน้าKeyValuePairนี้เป็นประเภทค่า (โครงสร้าง) ในขณะที่Tuple<>เป็นประเภทการอ้างอิง (คลาส) ดังนั้นการKeyValuePairจัดสรรในกองและTuple<>มีการจัดสรรในกองและทางเลือกที่ดีที่สุดมักจะถูกกำหนดโดยการขัดแย้งที่คลาสสิกของกองกับกองจัดสรรหน่วยความจำ ในระยะสั้นพื้นที่สแต็กมี จำกัด แต่โดยทั่วไปมีการเข้าถึงที่รวดเร็วมาก หน่วยความจำฮีปมีขนาดใหญ่กว่ามาก แต่ค่อนข้างช้ากว่า

KeyValuePair<T1, T2>อาจจะเป็นทางเลือกที่ดีกว่าถ้าทั้งสองคีย์และค่าประเภทพื้นฐาน (ประเภทค่าชอบint, bool, doubleฯลฯ ) หรือ structs ขนาดที่เล็ก ด้วยประเภทดั้งเดิมบนสแต็กการจัดสรรและการจัดสรรจะรวดเร็วทันใจ สิ่งนี้สามารถส่งผลต่อประสิทธิภาพโดยเฉพาะอย่างยิ่งเมื่อเป็นอาร์กิวเมนต์ของการเรียกใช้เมธอดแบบเรียกซ้ำ

ในทางกลับกันTuple<T1, T2>น่าจะเป็นทางเลือกที่ดีกว่าหากเป็นประเภทอ้างอิงT1หรือT2ประเภทใดประเภทหนึ่ง (เช่นคลาส) A KeyValuePairที่มีตัวชี้ไปยังประเภทการอ้างอิง (เป็นประเภทคีย์หรือค่า) การเรียงลำดับของการเอาชนะวัตถุประสงค์เนื่องจากวัตถุจะต้องได้รับการค้นหาบนฮีปอยู่ดี

นี่คือมาตรฐานที่ฉันพบออนไลน์: Tuple กับ KeyValuePair ปัญหาเดียวของเกณฑ์มาตรฐานนี้คือพวกเขาทดสอบKeyValuePair<string, string>กับTuple<string, string>และstringประเภทนี้เป็นประเภทที่ผิดปกติและพิเศษใน. NET ซึ่งสามารถทำงานได้ทั้งประเภทค่าและ / หรือประเภทการอ้างอิงขึ้นอยู่กับบริบทการดำเนินการ ผมเชื่อว่าจะได้รับการชนะที่ชัดเจนกับKeyValuePair<int, int> Tuple<int, int>แม้จะมีข้อบกพร่องอย่างไรก็ตามผลการศึกษาแสดงให้เห็นว่าความแตกต่างของประสิทธิภาพอาจมีนัยสำคัญ:

8.23 ns - จัดสรร Tuple
0.32 ns - จัดสรร KeyValuePair (เร็วขึ้น 25 เท่า!)

1.93 ns - ผ่าน Tuple เป็นอาร์กิวเมนต์
2.57 ns - ส่ง KeyValuePair เป็นอาร์กิวเมนต์

1.91 ns - Return Tuple
6.09 ns - Return KeyValuePair

2.79 ns - โหลด Tuple จากรายการ
4.18 ns - โหลด KeyValuePair จากรายการ


0

คุณถามคำถามผิดจริงๆคำถามที่ถูกต้องคือการใช้คลาส (Tuple) _ ดีกว่าโครงสร้าง (KVP) ซึ่งในกรณีนี้คำตอบคือสิ่งที่คุณต้องการใช้และคำตอบจะได้รับที่นี่โครงสร้างเทียบกับคลาส


2
เขาถามคำถามที่ถูกต้อง คำถามที่ดีกว่าสำหรับการใช้งานที่ส่อนัยอย่างชัดเจน
Greg

@Greg คำถามคือช็อคโกแลตหรือโซดาแบบไหนดีกว่ากัน แต่คำถามเฉพาะนั้นไม่มีจุดหมายและตอบได้ดีกว่าเป็นคำถามทั่วไปเกี่ยวกับอาหารและเครื่องดื่ม
MikeT

3
คำถาม defacto คือ "ฉันควรใช้ Tuples Vs. KeyPairs เมื่อใด" เป็นคำถามที่ถูกต้อง ฉันคิดว่าคุณแค่ติดอยู่กับความหมายของคำว่า "ดีกว่า"
Greg
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.