tuple ออกแบบมาเพื่อแก้ข้อกำหนดอะไร


94

ฉันกำลังดูคุณสมบัติ C # ใหม่ของสิ่งทู ฉันอยากรู้ว่าทูเพิลออกแบบมาเพื่อแก้ปัญหาอะไร

คุณใช้ tuples ทำอะไรในแอพของคุณ?

อัปเดต

ขอบคุณสำหรับคำตอบที่ผ่านมาให้ฉันดูว่าฉันมีสิ่งที่ตรงใจ ตัวอย่างที่ดีของทูเปิลถูกชี้ให้เห็นเป็นพิกัด หน้าตาแบบนี้ใช่ไหม

var coords = Tuple.Create(geoLat,geoLong);

จากนั้นใช้ทูเพิลดังนี้:

var myLatlng = new google.maps.LatLng("+ coords.Item1 + ", "+ coords.Item2 + ");

ถูกต้องหรือไม่



4
ฉันคิดได้สองคำตอบ ...
เที่ยงไหม

13
ถ้าแนวคิดเรื่อง "พิกัด" เหมาะสมกับคลาสฉันก็จะทำให้มันเป็นคลาส ใช้ tuples สำหรับสถานการณ์ที่มีไม่ได้บางอย่างที่เหมาะสม "ตรรกะทางธุรกิจ" แนวคิดสำหรับชุดของข้อมูลที่ justifies ทำให้ประเภทที่
Eric Lippert

13
พิกัดไม่ใช่ตัวอย่างที่ดีของทูเพิล Tuple ใน C # เป็นเพียงโซลูชันเฉพาะกิจในกรณีที่คุณต้องคืนค่า (จากฟังก์ชัน) สองค่า แทนที่จะตั้งค่าพารามิเตอร์ประเภทผลลัพธ์หนึ่งรายการบวกหนึ่งพารามิเตอร์การส่งคืนทูเพิลหนึ่งรายการจะดีกว่า วิธีนี้ทำให้คุณไม่ต้องประกาศพารามิเตอร์ที่สองล่วงหน้า ความแตกต่างนั้นชัดเจนยิ่งขึ้นใน C ++ (คุณสามารถสร้างผลลัพธ์ได้ แต่คุณไม่สามารถกำหนดพารามิเตอร์ out / ref ได้)
greenoldman

8
เพราะ python มีมันและ python ก็ไม่มีอะไรที่ C # ไม่มี;)
Evan Plaice

คำตอบ:


117

เมื่อเขียนโปรแกรมเป็นเรื่องปกติมากที่จะต้องการรวมกลุ่มของค่าที่มีเหตุผลเข้าด้วยกันซึ่งไม่มีความคล้ายคลึงกันเพียงพอที่จะแสดงเหตุผลในการสร้างคลาส

ภาษาการเขียนโปรแกรมจำนวนมากช่วยให้คุณสามารถจัดกลุ่มชุดของค่าที่ไม่เกี่ยวข้องกันอย่างมีเหตุผลโดยไม่ต้องสร้างประเภทด้วยวิธีเดียว:

void M(int foo, string bar, double blah)

ตรรกะนี้เหมือนกับเมธอด M ที่รับหนึ่งอาร์กิวเมนต์ซึ่งเป็น 3-tuple ของ int, string, double แต่ฉันหวังว่าคุณจะไม่ทำ:

class MArguments
{
   public int Foo { get; private set; } 
   ... etc

เว้นแต่ว่า MArguments จะมีความหมายอื่นในตรรกะทางธุรกิจ

แนวคิดของ "รวมกลุ่มข้อมูลที่ไม่เกี่ยวข้องกันไว้ด้วยกันในโครงสร้างบางส่วนที่มีน้ำหนักเบากว่าคลาส" มีประโยชน์ในหลาย ๆ ที่ไม่ใช่เฉพาะสำหรับรายการพารามิเตอร์ที่เป็นทางการ จะมีประโยชน์เมื่อเมธอดมีสองสิ่งที่ต้องส่งคืนหรือเมื่อคุณต้องการคีย์พจนานุกรมจากข้อมูลสองข้อมูลแทนที่จะเป็นหนึ่งข้อมูลและอื่น ๆ

ภาษาเช่น F # ซึ่งรองรับประเภททูเปิลให้ความยืดหยุ่นแก่ผู้ใช้เป็นอย่างมาก เป็นชุดข้อมูลที่มีประโยชน์อย่างยิ่ง ทีม BCL ตัดสินใจที่จะทำงานร่วมกับทีม F # เพื่อสร้างมาตรฐานของทูเพิลประเภทเดียวสำหรับเฟรมเวิร์กเพื่อให้ทุกภาษาได้รับประโยชน์จากพวกเขา

อย่างไรก็ตาม ณ จุดนี้ยังไม่มีการรองรับภาษาสำหรับทูเปิลใน C # Tuples เป็นเพียงประเภทข้อมูลอื่นเช่นเดียวกับคลาส Framework อื่น ๆ ไม่มีอะไรพิเศษเกี่ยวกับพวกเขา เรากำลังพิจารณาเพิ่มการสนับสนุนที่ดีขึ้นสำหรับสิ่งที่เพิ่มขึ้นใน C # เวอร์ชันสมมุติในอนาคต หากใครมีความคิดเห็นเกี่ยวกับคุณสมบัติที่เกี่ยวข้องกับสิ่งที่คุณต้องการดูเรายินดีที่จะส่งต่อให้กับทีมออกแบบ สถานการณ์ที่เป็นจริงมีความน่าเชื่อมากกว่าเนื้อหาทางทฤษฎี


1
@MalcomTucker: อะซิงโครไนซ์และความขนานนั้นอยู่ในใจของเราอย่างแน่นอนในฐานะพื้นที่ที่อุดมสมบูรณ์ซึ่งสามารถใช้เครื่องมือภาษาเพื่อแก้ปัญหาที่แท้จริงได้ ฉันไม่คิดว่าเวิร์กโฟลว์แบบอะซิงโครนัสแบบ F # จำเป็นต้องเหมาะสมที่สุดสำหรับ C # แต่มันเป็นแรงบันดาลใจอย่างแน่นอน
Eric Lippert

60
แม้ว่าสิ่งที่มีประโยชน์จะมีประโยชน์ แต่ข้อเสียเปรียบประการหนึ่งคือความชัดเจน มันยากที่จะอ่านและทำความเข้าใจรหัสที่หมายถึงItem1, Item2ฯลฯ ... ถ้า tuples เคยทำบรรลุสนับสนุนภาษาใน C # มันจะยอดเยี่ยมที่จะช่วยให้สมาชิกของพวกเขาที่จะตั้งชื่อ (หรืออย่างน้อยนามแฝง) ในลักษณะที่ช่วยให้รหัสที่ใช้ ให้เข้าใจได้มากขึ้น ในอนาคตอันเลวร้ายเช่นนี้ฉันชอบที่จะเห็นสิ่งที่มี "รูปร่าง" ที่เหมาะสมเป็นพารามิเตอร์ทางกฎหมายสำหรับวิธีการที่ใช้พารามิเตอร์แต่ละตัว (และในทางกลับกัน) ดังนั้นสามารถส่งผ่านไปTuple<int,string,bool> M(int,string,bool)มันจะทำให้วิธีการบันทึกง่ายขึ้นมาก
LBushkin

2
เหล่านี้ "tuples" มีพื้นpublicการเข้าถึงที่ไม่ระบุชื่อ structประเภทสมาชิกที่ไม่มีชื่อ ฉันอยากให้โปรแกรมเมอร์เขียน a structกับสมาชิกที่มีชื่อและส่งกลับมาแทนที่จะต้องจัดการกับสิ่งtupleที่ไม่ได้บอกอะไรเกี่ยวกับความหมายของสมาชิก
bobobobo

1
@ Hi-Angel: ข้อโต้แย้งไม่ได้เกี่ยวกับการเล่นลิ้นเกี่ยวกับสิ่งที่นับเป็นทูเปิลและสิ่งที่ไม่ได้ แต่เป็นชุดของคุณสมบัติที่นักพัฒนาสายธุรกิจสมัยใหม่สามารถใช้เพื่อเพิ่มผลผลิตของพวกเขาได้ LBushkin กำลังแสดงคำขอคุณลักษณะที่ทีมออกแบบได้ยินตลอดเวลานั่นคือความปรารถนาที่จะสร้าง "ประเภทระเบียน" บางประเภทโดยไม่ต้องเดือดร้อนและเสียค่าใช้จ่ายในการสร้างทั้งชั้นเรียนเพียงเพื่อรวบรวมข้อมูลสองสามช่องไว้ด้วยกัน C # มีคุณสมบัติสำหรับวิธีการนี้อยู่แล้ว เรียกว่า "รายการพารามิเตอร์"
Eric Lippert

2
@ Hi-Angel: คุณอาจจะไม่โต้แย้งว่า "ถ้าคุณต้องการเข้าถึงพารามิเตอร์เมธอดของคุณตามชื่อคุณควรสร้างคลาสแยกต่างหาก" เพราะดูเหมือนว่าจะหนักมาก แต่ดูเหมือนว่าจะหนักเพราะเราคุ้นเคยกับ ความสามารถในการทันทีผูกกันชุดของตัวแปรโดยพลการโดยพลการและประเภทชื่อเมื่อเรียกวิธีการ ลองนึกภาพว่าไม่มีภาษาใดที่มีคุณลักษณะนั้น ทุกวิธีสามารถใช้อาร์กิวเมนต์เดียวเท่านั้นและหากคุณต้องการส่งผ่านสองข้อคุณจะต้องสร้างประเภทและส่งตัวอย่างของมัน
Eric Lippert

22

Tuples นำเสนอการใช้งานคอลเลกชันที่ไม่เปลี่ยนรูป

นอกเหนือจากการใช้ทูเปิลทั่วไป:

  • เพื่อจัดกลุ่มค่าส่วนกลางเข้าด้วยกันโดยไม่ต้องสร้างคลาส
  • เพื่อคืนค่าหลายค่าจากฟังก์ชัน / วิธีการ
  • ฯลฯ ...

วัตถุที่ไม่เปลี่ยนรูปเป็นด้ายที่ปลอดภัยโดยเนื้อแท้:

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

จาก"Immutable Object"บนวิกิพีเดีย


ขอบคุณสำหรับการเพิ่มข้อมูลเพิ่มเติมในคำถาม ชื่นชมมาก
Chaddeus

หากคุณต้องการคอลเลกชันที่ไม่เปลี่ยนรูปคุณควรใช้คอลเลกชันที่ไม่เปลี่ยนรูปไม่ใช่ Tuple ความแตกต่างคือสำหรับคอลเลกชันที่ไม่เปลี่ยนรูปส่วนใหญ่คุณไม่จำเป็นต้องระบุจำนวนองค์ประกอบในเวลาคอมไพล์
BlueRaja - Danny Pflughoeft

@ BlueRaja-DannyPflughoeft ย้อนกลับไปเมื่อฉันเขียนคำตอบนี้คลาสคอลเลกชัน C # ที่ไม่เปลี่ยนรูปยังไม่สามารถใช้ได้ใน BCL เดาว่าฉันจะเปลี่ยน 'collection' เป็น 'object' เนื่องจาก MS neutered the Tuple ใช้งานใน C #
Evan Plaice

12

มีทางเลือกให้refหรือoutถ้าคุณมีวิธีการที่ต้องการส่งคืนอ็อบเจ็กต์ใหม่หลายรายการเป็นส่วนหนึ่งของการตอบสนอง

นอกจากนี้ยังช่วยให้คุณสามารถใช้ประเภทในตัวเป็นประเภทส่งคืนได้หากสิ่งที่คุณต้องทำคือการผสมสองหรือสามประเภทที่มีอยู่และคุณไม่ต้องการเพิ่มคลาส / โครงสร้างสำหรับชุดค่าผสมนี้เท่านั้น (เคยต้องการให้ฟังก์ชันส่งคืนประเภทที่ไม่ระบุตัวตนหรือไม่นี่คือคำตอบบางส่วนสำหรับสถานการณ์นั้น)


ประณาม. ดี. ฉันหวังว่าฉันจะได้ตรวจสอบสิ่งที่ทูเปิล - เมื่อไม่กี่ปีที่ผ่านมา;)
sabiland

10

การมีประเภท "คู่" มักจะเป็นประโยชน์ซึ่งใช้ในสถานการณ์ที่รวดเร็ว (เช่นการคืนค่าสองค่าจากวิธีการ) Tuples เป็นส่วนสำคัญของภาษาที่ใช้งานได้เช่น F # และ C # จะเลือกภาษาเหล่านี้


System.Web.UI มีระดับคู่msdn.microsoft.com/en-us/library/system.web.ui.pair.aspx
StingyJack

5

มีประโยชน์มากสำหรับการคืนค่าสองค่าจากฟังก์ชัน


1
อาจจะเป็นการตัดประเภทที่ไม่ระบุตัวตน?
bloparod

1
ฉันเห็นว่าพวกเขาเป็นโครงสร้างที่ไม่ระบุตัวตน
Matt Evans

4

โดยส่วนตัวแล้วฉันพบว่าทูเปิลเป็นส่วนหนึ่งของการพัฒนาเมื่อคุณอยู่ในวงจรการสืบสวนหรือแค่ "เล่น" เนื่องจาก Tuple เป็นแบบทั่วไปฉันมักจะนึกถึงเมื่อทำงานกับพารามิเตอร์ทั่วไปโดยเฉพาะอย่างยิ่งเมื่อต้องการพัฒนาโค้ดทั่วไปและฉันเริ่มต้นที่ส่วนท้ายรหัสแทนที่จะถามตัวเองว่า "ฉันจะเรียกสิ่งนี้อย่างไร มอง?".

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

แน่นอนว่ามีวิธีการขยายอยู่เสมอ แต่บ่อยครั้งที่คุณไม่ต้องการขยายโค้ดพิเศษนั้นไปยังการใช้งานทั่วไป

มีหลายครั้งที่ฉันต้องการแสดงข้อมูลเป็นทูเพิล แต่ไม่มีทูเปิล (VS2008) ซึ่งในกรณีนี้ฉันเพิ่งสร้างคลาส Tuple ของตัวเอง - และฉันไม่ทำให้เธรดปลอดภัย (ไม่เปลี่ยนรูป)

ดังนั้นฉันเดาว่าฉันมีความเห็นว่า Tuples เป็นโปรแกรมที่ขี้เกียจเนื่องจากเสียชื่อประเภทที่อธิบายวัตถุประสงค์ ค่าใช้จ่ายอื่น ๆ คือคุณต้องประกาศลายเซ็นของ Tuple ไม่ว่าจะใช้เป็นพารามิเตอร์ หลังจากวิธีการหลายอย่างที่เริ่มดูบวมคุณอาจรู้สึกเหมือนฉันว่ามันคุ้มค่าที่จะสร้างคลาสเพราะมันจะล้างลายเซ็นของวิธีการ

ฉันมักจะเริ่มต้นด้วยการให้ชั้นเรียนเป็นสมาชิกสาธารณะของชั้นเรียนที่คุณทำงานอยู่แล้ว แต่ในขณะที่มันขยายออกไปไกลกว่าการรวบรวมค่าเพียงอย่างเดียวมันก็กลายเป็นไฟล์ของตัวเองและฉันย้ายมันออกจากชั้นเรียนที่มี

ดังนั้นเมื่อมองย้อนกลับไปฉันเชื่อว่าฉันใช้ Tuples เมื่อฉันไม่ต้องการที่จะออกไปเขียนชั้นเรียนและแค่อยากคิดเกี่ยวกับสิ่งที่ฉันเขียนในตอนนี้ ซึ่งหมายความว่าลายเซ็นของ Tuple อาจมีการเปลี่ยนแปลงค่อนข้างมากในข้อความครึ่งชั่วโมงในขณะที่ฉันคิดว่าฉันต้องการข้อมูลใดสำหรับวิธีนี้และวิธีการคืนค่าที่เคยจะคืนค่า

ถ้าฉันมีโอกาส refactor code ฉันมักจะตั้งคำถามกับสถานที่ของ Tuple ในนั้น


3

คำถามเก่าตั้งแต่ปี 2010 และตอนนี้ในปี 2017 Dotnet มีการเปลี่ยนแปลงและฉลาดขึ้น

C # 7 แนะนำการรองรับภาษาสำหรับทูเปิลซึ่งเปิดใช้งานชื่อความหมายสำหรับฟิลด์ของทูเพิลโดยใช้ทูเพิลชนิดใหม่ที่มีประสิทธิภาพมากขึ้น

ในเทียบกับ 2017 และ. Net 4.7 (หรือติดตั้ง nuget package System.ValueTuple) คุณสามารถสร้าง / ใช้ทูเพิลได้อย่างมีประสิทธิภาพและง่ายดาย:

     var person = (Id:"123", Name:"john"); //create tuble with two items
     Console.WriteLine($"{person.Id} name:{person.Name}") //access its fields

การส่งคืนค่ามากกว่าหนึ่งค่าจากวิธีการ:

    public (double sum, double average) ComputeSumAndAverage(List<double> list)
    {
       var sum= list.Sum();
        var average = sum/list.Count;
        return (sum, average);
    }

    How to use:

        var list=new List<double>{1,2,3};
        var result = ComputeSumAndAverage(list);
        Console.WriteLine($"Sum={result.sum} Average={result.average}");    

สำหรับรายละเอียดเพิ่มเติมโปรดอ่าน: https://docs.microsoft.com/en-us/dotnet/csharp/tuples


1

Tuple มักใช้เพื่อส่งคืนค่าหลายค่าจากฟังก์ชันเมื่อคุณไม่ต้องการสร้างประเภทเฉพาะ หากคุณคุ้นเคยกับ Python Python มีมานานแล้ว


1

ส่งคืนค่ามากกว่าหนึ่งค่าจากฟังก์ชัน getCoordinates () ไม่มีประโยชน์มากนักหากส่งคืนค่า x หรือ y หรือ z แต่การสร้างคลาสและอ็อบเจ็กต์แบบเต็มเพื่อเก็บสาม ints ก็ดูเหมือนจะมีน้ำหนักมาก


1

การใช้งานทั่วไปอาจเป็นการหลีกเลี่ยงการสร้างคลาส / โครงสร้างที่มีเพียง 2 ฟิลด์แทนที่จะสร้าง Tuple (หรือ KeyValuePair ในตอนนี้) มีประโยชน์เป็นค่าส่งคืนหลีกเลี่ยงการส่ง N out params ...


0

ฉันพบว่า KeyValuePair กำลังรีเฟรชใน C # เพื่อวนซ้ำคู่ค่าคีย์ในพจนานุกรม


KeyValuePairสามารถดูเป็นวิธีแก้ปัญหาเฉพาะหน้าได้ ใน Python การทำซ้ำบนสิ่งที่dictส่งคืนเพียงแค่ (คีย์ค่า)
dan04

ใช่เหมือนงูเหลือม :-) ฉันไม่รู้ว่า KeyValuePair ใน c # ไม่ใช่ทูเพิล?
Jubal

0

มันมีประโยชน์มากในขณะที่คืนค่าจากฟังก์ชัน เราสามารถมีค่าย้อนกลับได้หลายค่าและนี่ก็ค่อนข้างประหยัดในบางสถานการณ์


0

ฉันสะดุดกับเกณฑ์มาตรฐานประสิทธิภาพระหว่างคู่ทูเปิลและคีย์ - ค่าและคุณอาจคิดว่ามันน่าสนใจ โดยสรุปกล่าวว่าทูเปิลมีข้อได้เปรียบเนื่องจากเป็นคลาสดังนั้นจึงถูกเก็บไว้ในฮีปไม่ใช่ในสแต็กและเมื่อส่งผ่านไปรอบ ๆ เนื่องจากอาร์กิวเมนต์ตัวชี้เป็นสิ่งเดียวที่จะเกิดขึ้น แต่ KeyValuePair เป็นโครงสร้างดังนั้นจึงจัดสรรได้เร็วกว่า แต่จะช้ากว่าเมื่อใช้

http://www.dotnetperls.com/tuple-keyvaluepair

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