เหตุใดประเภท Tuple ใหม่ใน. Net 4.0 จึงเป็นประเภทอ้างอิง (คลาส) และไม่ใช่ชนิดค่า (โครงสร้าง)


89

ไม่มีใครรู้คำตอบและ / หรือมีความคิดเห็นเกี่ยวกับเรื่องนี้?

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


1
สำหรับทุกคนที่สะดุดที่นี่หลังจากปี 2016 ใน C # 7 และใหม่กว่าอักษร Tuple ValueTuple<...>มีครอบครัวประเภท ดูข้อมูลอ้างอิงที่ C # tuple types
Tamir Daniely

คำตอบ:


94

Microsoft สร้างประเภทการอ้างอิงทุกประเภททูเปิลเพื่อความเรียบง่าย

โดยส่วนตัวฉันคิดว่านี่เป็นความผิดพลาด Tuples ที่มีมากกว่า 4 ช่องนั้นผิดปกติมากและควรแทนที่ด้วยทางเลือกที่หลากหลายกว่าอยู่ดี (เช่นประเภทระเบียนใน F #) ดังนั้นจึงมีเพียงสิ่งเล็ก ๆ ที่น่าสนใจเท่านั้น การวัดประสิทธิภาพของฉันเองแสดงให้เห็นว่าสิ่งที่ไม่ได้บรรจุกล่องที่มีขนาดสูงสุด 512 ไบต์ยังคงเร็วกว่าสิ่งที่เป็นกล่อง

แม้ว่าประสิทธิภาพของหน่วยความจำจะเป็นเรื่องที่น่ากังวล แต่ฉันเชื่อว่าปัญหาที่สำคัญคือค่าใช้จ่ายของตัวรวบรวมขยะ. NET การจัดสรรและการรวบรวมมีราคาแพงมากบน. NET เนื่องจากตัวรวบรวมขยะไม่ได้รับการปรับให้เหมาะสมมากนัก (เช่นเมื่อเทียบกับ JVM) ยิ่งไปกว่านั้น. NET GC (เวิร์กสเตชัน) เริ่มต้นยังไม่ได้รับการขนาน ดังนั้นโปรแกรมคู่ขนานที่ใช้ทูเปิลจึงหยุดชะงักเนื่องจากคอร์ทั้งหมดต่อสู้เพื่อตัวรวบรวมขยะที่ใช้ร่วมกันทำลายความสามารถในการปรับขนาด นี่ไม่ใช่แค่ความกังวลที่สำคัญ แต่ AFAIK ถูกไมโครซอฟท์ละเลยอย่างสิ้นเชิงเมื่อตรวจสอบปัญหานี้

ข้อกังวลอีกประการหนึ่งคือการจัดส่งเสมือน ประเภทการอ้างอิงสนับสนุนประเภทย่อยดังนั้นโดยทั่วไปสมาชิกของพวกเขาจะถูกเรียกใช้ผ่านการจัดส่งเสมือน ในทางตรงกันข้ามประเภทค่าไม่สามารถรองรับชนิดย่อยได้ดังนั้นการเรียกสมาชิกจึงไม่คลุมเครือและสามารถดำเนินการเป็นการเรียกฟังก์ชันโดยตรงได้เสมอ การจัดส่งเสมือนมีราคาแพงมากสำหรับฮาร์ดแวร์สมัยใหม่เนื่องจาก CPU ไม่สามารถคาดเดาได้ว่าตัวนับโปรแกรมจะสิ้นสุดที่ใด JVM มีความยาวมากในการปรับการจัดส่งเสมือนให้เหมาะสม แต่. NET ไม่ทำ อย่างไรก็ตาม. NET มีการหลีกเลี่ยงจากการจัดส่งเสมือนในรูปแบบของชนิดค่า ดังนั้นการแสดง tuples เป็นประเภทค่าจึงสามารถปรับปรุงประสิทธิภาพที่นี่ได้อย่างมาก ตัวอย่างเช่นการโทรGetHashCode บน 2-tuple หนึ่งล้านครั้งใช้เวลา 0.17 วินาที แต่การเรียกมันบนโครงสร้างที่เทียบเท่าจะใช้เวลาเพียง 0.008 วินาทีนั่นคือชนิดของค่านั้นเร็วกว่าชนิดอ้างอิงถึง 20 เท่า

สถานการณ์จริงที่มักเกิดปัญหาด้านประสิทธิภาพกับสิ่งเหล่านี้ขึ้นอยู่กับการใช้ทูเปิลเป็นคีย์ในพจนานุกรม ฉันสะดุดกับเธรดนี้จริงๆโดยไปตามลิงค์จากคำถาม Stack Overflow F # เรียกใช้อัลกอริทึมของฉันช้ากว่า Python! โดยที่โปรแกรม F # ของผู้เขียนช้ากว่า Python ของเขาอย่างแม่นยำเพราะเขาใช้ tuples แบบบรรจุกล่อง การแกะกล่องด้วยตนเองโดยใช้structประเภทที่เขียนด้วยมือทำให้โปรแกรม F # ของเขาเร็วขึ้นหลายเท่าและเร็วกว่า Python ปัญหาเหล่านี้จะไม่เกิดขึ้นหากสิ่งที่เพิ่มขึ้นแสดงด้วยประเภทค่าและไม่ใช่ประเภทอ้างอิงที่ขึ้นต้นด้วย ...


2
@ เบนท์: ใช่นั่นคือสิ่งที่ฉันทำเมื่อฉันเจอทูเปิลบนเส้นทางที่ร้อนแรงใน F # จะเป็นการดีถ้าพวกเขาได้จัดเตรียม tuples ทั้งแบบบรรจุกล่องและแบบไม่มีกล่องใน. NET Framework แม้ว่า ...
JD

18
เกี่ยวกับการจัดส่งเสมือนฉันคิดว่าการตำหนิของคุณถูกใส่ผิดตำแหน่ง: Tuple<_,...,_>ประเภทอาจถูกปิดผนึกซึ่งในกรณีนี้ไม่จำเป็นต้องใช้การจัดส่งเสมือนแม้ว่าจะเป็นประเภทอ้างอิงก็ตาม ฉันสงสัยมากว่าทำไมพวกเขาถึงไม่ปิดผนึกมากกว่าทำไมถึงเป็นประเภทอ้างอิง
kvb

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

2
"tuples ที่ไม่ได้บรรจุกล่องสูงสุด 512 ไบต์อาจยังเร็วกว่าแบบบรรจุกล่อง" - สถานการณ์ใด คุณอาจจัดสรรโครงสร้าง 512B ได้เร็วกว่าอินสแตนซ์คลาสที่มีข้อมูล 512B แต่การส่งผ่านไปรอบ ๆ จะช้ากว่า 100 เท่า (สมมติว่า x86) มีบางอย่างที่ฉันมองข้ามไปไหม?
Groo


45

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

แทนที่จะให้สิ่งสองสิ่งบางอย่างเป็นประเภทค่าและอื่น ๆ เป็นประเภทอ้างอิงและบังคับให้นักพัฒนาทราบว่าสิ่งใดที่ฉันคิดว่าคนที่ Microsoft คิดว่าทำให้ประเภทการอ้างอิงทั้งหมดนั้นง่ายกว่า

อ๊ะสงสัยคอนเฟิร์ม! โปรดดูBuilding Tuple :

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


3
การสนทนาที่ยอดเยี่ยมที่นี่: blogs.msdn.com/bclteam/archive/2009/07/07/…
Keith Adler

ฉันเข้าใจแล้ว ฉันยังสับสนเล็กน้อยว่าประเภทของค่าไม่มีความหมายอะไรในทางปฏิบัติที่นี่: P
Bent Rasmussen

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

7
ขีด จำกัด "16 ไบต์" ของคุณเป็นของปลอม เมื่อฉันทดสอบสิ่งนี้บน. NET 4 ฉันพบว่า GC นั้นช้ามากจนสิ่งที่ไม่ได้บรรจุกล่องถึง 512 ไบต์ยังคงเร็วกว่า ฉันยังตั้งคำถามกับผลการวัดประสิทธิภาพของ Microsoft ฉันพนันได้เลยว่าพวกเขาเพิกเฉยต่อความขนาน (คอมไพเลอร์ F # ไม่ขนานกัน) และนั่นคือสิ่งที่การหลีกเลี่ยง GC จ่ายออกไปเพราะ GC เวิร์กสเตชันของ. NET นั้นไม่ขนานกัน
JD

ด้วยความอยากรู้อยากเห็นฉันสงสัยว่าทีมคอมไพเลอร์ได้ทดสอบแนวคิดในการทำให้สิ่งทอเป็นโครงสร้างEXPOSED-FIELDหรือไม่? หากมีตัวอย่างของประเภทที่มีลักษณะที่แตกต่างกันและความต้องการของอินสแตนซ์ซึ่งเป็นเหมือนยกเว้นลักษณะซึ่งเป็นที่แตกต่างกันเป็น struct สัมผัสสนามสามารถประสบความสำเร็จที่มากเร็วกว่าชนิดอื่น ๆ และประโยชน์เท่านั้นเติบโตเป็น structs รับ ใหญ่ขึ้น.
supercat

7

ถ้าชนิด. NET System.Tuple <... >ถูกกำหนดให้เป็นโครงสร้างก็จะไม่สามารถปรับขนาดได้ ตัวอย่างเช่น ternary tuple ของจำนวนเต็มยาวในปัจจุบันมีขนาดดังนี้:

type Tuple3 = System.Tuple<int64, int64, int64>
type Tuple33 = System.Tuple<Tuple3, Tuple3, Tuple3>
sizeof<Tuple3> // Gets 4
sizeof<Tuple33> // Gets 4

หาก ternary tuple ถูกกำหนดให้เป็นโครงสร้างผลลัพธ์จะเป็นดังนี้ (ตามตัวอย่างการทดสอบที่ฉันใช้):

sizeof<Tuple3> // Would get 32
sizeof<Tuple33> // Would get 104

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

let t3 = 1L, 2L, 3L
let t33 = t3, t3, t3

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

ตามหลักการแล้วจะมีสิ่งทอทั้งแบบ "คลาส" และ "โครงสร้าง" ทั้งสองแบบที่รองรับวากยสัมพันธ์ใน F #!

แก้ไข (2017-10-07)

ตอนนี้สิ่งที่เป็นโครงสร้างได้รับการสนับสนุนอย่างเต็มที่ดังนี้:

  • สร้างขึ้นใน mscorlib (.NET> = 4.7) เป็นSystem.ValueTuple
  • พร้อมใช้งานเป็นNuGetสำหรับเวอร์ชันอื่น ๆ
  • รองรับวากยสัมพันธ์ในC #> = 7
  • การสนับสนุนไวยากรณ์ในF #> = 4.1

2
หากหลีกเลี่ยงการคัดลอกที่ไม่จำเป็นโครงสร้างของฟิลด์แบบเปิดเผยทุกขนาดจะมีประสิทธิภาพมากกว่าคลาสที่ไม่เปลี่ยนรูปที่มีขนาดเท่ากันเว้นแต่ว่าแต่ละอินสแตนซ์จะถูกคัดลอกมากพอที่ค่าใช้จ่ายในการคัดลอกดังกล่าวจะเอาชนะต้นทุนในการสร้างฮีปอ็อบเจ็กต์ ( จำนวนสำเนาที่คุ้มทุนจะแตกต่างกันไปตามขนาดวัตถุ) การคัดลอกดังกล่าวอาจหลีกเลี่ยงไม่ได้หากใครต้องการโครงสร้างที่แสร้งทำเป็นไม่เปลี่ยนรูป แต่โครงสร้างที่ออกแบบมาให้ปรากฏเป็นชุดของตัวแปร (ซึ่งเป็นโครงสร้างที่มี ) สามารถใช้งานได้อย่างมีประสิทธิภาพแม้ว่าจะมีขนาดใหญ่ก็ตาม
supercat

2
อาจเป็นไปได้ว่า F # ไม่ได้เล่นกับแนวคิดในการส่งผ่านโครงสร้างโดยrefหรืออาจไม่ชอบความจริงที่เรียกว่า "โครงสร้างที่ไม่เปลี่ยนรูป" ไม่ได้โดยเฉพาะอย่างยิ่งเมื่ออยู่ในกล่อง มันแย่เกินไป. net ไม่เคยใช้แนวคิดการส่งผ่านพารามิเตอร์โดยบังคับconst refเนื่องจากในหลาย ๆ กรณีความหมายเช่นนี้เป็นสิ่งที่จำเป็นจริงๆ
supercat

1
อนึ่งฉันถือว่าต้นทุนตัดจำหน่ายของ GC เป็นส่วนหนึ่งของต้นทุนในการจัดสรรวัตถุ หากจำเป็นต้องใช้ L0 GC หลังจากการจัดสรรทุกๆเมกะไบต์ค่าใช้จ่ายในการจัดสรร 64 ไบต์จะอยู่ที่ประมาณ 1/16,000 ของต้นทุน L0 GC บวกเศษของต้นทุนของ L1 หรือ L2 GC ใด ๆ ที่จำเป็นในฐานะ a ผลของมัน
supercat

4
"ฉันคิดว่าผลคูณของความน่าจะเป็นที่เกิดขึ้นครั้งความเสียหายที่อาจเกิดขึ้นจะสูงกว่าโครงสร้างที่เป็นอยู่ในปัจจุบันมาก" FWIW ฉันไม่ค่อยเห็นทูเปิลในป่าและมองว่ามันเป็นข้อบกพร่องในการออกแบบ แต่ฉันมักจะเห็นผู้คนต่อสู้กับประสิทธิภาพที่แย่มากเมื่อใช้ (ref) tuples เป็นคีย์ใน a Dictionaryเช่นที่นี่: stackoverflow.com/questions/5850243 / …
JD

3
@ จอนเป็นเวลาสองปีแล้วที่ฉันเขียนคำตอบนี้และตอนนี้ฉันเห็นด้วยกับคุณว่ามันจะดีกว่าถ้าอย่างน้อย 2 และ 3-tuples เป็นโครงสร้าง มีการเสนอคำแนะนำเสียงของผู้ใช้ภาษา F # ในเรื่องนี้ ปัญหานี้มีความเร่งด่วนเนื่องจากมีการเติบโตอย่างมากของแอปพลิเคชันในข้อมูลขนาดใหญ่การเงินเชิงปริมาณและการเล่นเกมในช่วงไม่กี่ปีที่ผ่านมา
Marc Sigrist

4

สำหรับ 2-tuples คุณยังคงสามารถใช้ KeyValuePair <TKey, TValue> จาก Common Type System เวอร์ชันก่อนหน้าได้เสมอ เป็นประเภทมูลค่า

การชี้แจงเล็กน้อยสำหรับบทความของ Matt Ellis ก็คือความแตกต่างในการใช้ความหมายระหว่างประเภทการอ้างอิงและประเภทของค่านั้นเป็นเพียง "เล็กน้อย" เมื่อความไม่เปลี่ยนรูปมีผล (ซึ่งแน่นอนว่าจะเป็นเช่นนั้นในที่นี้) อย่างไรก็ตามฉันคิดว่ามันน่าจะดีที่สุดในการออกแบบ BCL ที่จะไม่ทำให้เกิดความสับสนในการให้ Tuple ข้ามไปยังประเภทการอ้างอิงในบางเกณฑ์


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

ขอขอบคุณที่เพิ่มกฎที่มีประโยชน์นี้ ฉันหวังว่าคุณจะไม่เข้าใจผิดในตำแหน่งของฉัน: ฉันเป็นคนขี้ยาที่มีคุณค่า ( stackoverflow.com/a/14277068ไม่ควรสงสัย)
Glenn Slayden

ประเภทค่าเป็นหนึ่งในคุณสมบัติที่ยอดเยี่ยมของ. net แต่น่าเสียดายที่ผู้ที่เขียน msdn dox ล้มเหลวในการรับรู้ว่ามีกรณีการใช้งานที่ไม่ปะติดปะต่อกันหลายกรณีและกรณีการใช้งานที่แตกต่างกันควรมีแนวทางที่แตกต่างกัน รูปแบบของ struct MSDN แนะนำควรจะใช้เฉพาะกับ structs ที่เป็นตัวแทนของค่าคุณสมบัติเหมือนกันแต่ถ้าความต้องการที่จะเป็นตัวแทนค่าบางอย่างอิสระยึดร่วมกับเทปท่อหนึ่งไม่ควรใช้ว่ารูปแบบของ struct - ควรใช้ struct กับ เปิดพื้นที่สาธารณะ
supercat

0

ฉันไม่รู้ แต่คุณเคยใช้ F # Tuples เป็นส่วนหนึ่งของภาษาหรือไม่ ถ้าฉันสร้าง. dll และส่งคืน Tuples ประเภทหนึ่งก็คงจะดีถ้ามีประเภทที่จะใส่เข้าไปฉันสงสัยว่าตอนนี้ F # เป็นส่วนหนึ่งของภาษา (.Net 4) มีการปรับเปลี่ยนบางอย่างกับ CLR เพื่อรองรับโครงสร้างทั่วไปบางอย่าง ใน F #

จากhttp://en.wikibooks.org/wiki/F_Sharp_Programming/Tuples_and_Records

let scalarMultiply (s : float) (a, b, c) = (a * s, b * s, c * s);;

val scalarMultiply : float -> float * float * float -> float * float * float

scalarMultiply 5.0 (6.0, 10.0, 20.0);;
val it : float * float * float = (30.0, 50.0, 100.0)
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.