วิธีที่ฉันเห็นมัน Tuple เป็นทางลัดในการเขียนคลาสผลลัพธ์ (ฉันแน่ใจว่ามีการใช้อื่น ๆ ด้วย)
มีประโยชน์อื่น ๆ ที่มีคุณค่าสำหรับTuple<>
- ส่วนใหญ่เกี่ยวข้องกับการแยกความหมายของกลุ่มเฉพาะประเภทที่ใช้โครงสร้างที่คล้ายกันและรักษาพวกเขาเพียงแค่สั่งชุดของค่า ในทุกกรณีประโยชน์ของสิ่งอันดับคือพวกเขาหลีกเลี่ยงความยุ่งเหยิงในเนมสเปซของคุณด้วยคลาสข้อมูลอย่างเดียวที่เปิดเผยคุณสมบัติ แต่ไม่ใช่วิธีการ
นี่คือตัวอย่างของการใช้งานที่สมเหตุสมผลสำหรับTuple<>
:
var opponents = new Tuple<Player,Player>( playerBob, playerSam );
ในตัวอย่างข้างต้นเราต้องการแสดงคู่ของคู่ต่อสู้ tuple เป็นวิธีที่สะดวกในการจับคู่อินสแตนซ์เหล่านี้โดยไม่ต้องสร้างคลาสใหม่ นี่เป็นอีกตัวอย่าง:
var pokerHand = Tuple.Create( card1, card2, card3, card4, card5 );
มือโป๊กเกอร์สามารถคิดได้ว่าเป็นเพียงชุดไพ่ - และ tuple (อาจ) เป็นวิธีที่สมเหตุสมผลในการแสดงแนวคิดนั้น
ตั้งค่าความเป็นไปได้ที่ฉันพลาดจุด Tuples เป็นตัวอย่างที่ Tuple เป็นตัวเลือกการออกแบบที่ไม่ดีหรือไม่?
การส่งคืนTuple<>
อินสแตนซ์ที่พิมพ์อย่างมากซึ่งเป็นส่วนหนึ่งของ API สาธารณะสำหรับประเภทสาธารณะไม่ค่อยเป็นความคิดที่ดี ในขณะที่คุณรับรู้สิ่งอันดับ tuples ต้องการฝ่ายต่างๆที่เกี่ยวข้อง (ผู้เขียนห้องสมุดผู้ใช้ห้องสมุด) เพื่อตกลงล่วงหน้าเกี่ยวกับวัตถุประสงค์และการตีความประเภท tuple ที่ใช้ มันท้าทายพอที่จะสร้าง API ที่ใช้งานง่ายและชัดเจนโดยใช้Tuple<>
สาธารณะเท่านั้นบดบังเจตนาและพฤติกรรมของ API
ประเภทที่ไม่ระบุชื่อเป็นชนิดของ tuple - อย่างไรก็ตามมันจะถูกพิมพ์อย่างรุนแรงและอนุญาตให้คุณระบุชื่อที่ชัดเจนและให้ข้อมูลสำหรับคุณสมบัติที่เป็นของประเภทนั้น แต่ประเภทที่ไม่ระบุตัวตนนั้นยากต่อการใช้งานในวิธีการที่แตกต่างกัน - ส่วนใหญ่จะถูกเพิ่มเข้ามาเพื่อรองรับเทคโนโลยีเช่น LINQ ซึ่งการคาดการณ์จะสร้างประเภทที่ปกติแล้วเราไม่ต้องการกำหนดชื่อ (ใช่ฉันรู้ว่าประเภทไม่ระบุชื่อที่มีประเภทเดียวกันและคุณสมบัติที่มีชื่อจะถูกรวมโดยคอมไพเลอร์)
My กฎของหัวแม่มือคือ: ถ้าคุณจะกลับมาได้จากอินเตอร์เฟซที่สาธารณะของคุณ - ทำให้มันเป็นชื่อประเภท
กฎง่ายๆอีกข้อของฉันสำหรับการใช้สิ่งอันดับคือ: อาร์กิวเมนต์เมธอดชื่อและตัวแปร localc ประเภทTuple<>
อย่างชัดเจนที่สุด - ทำให้ชื่อเป็นตัวแทนของความหมายของความสัมพันธ์ระหว่างองค์ประกอบของสิ่งอันดับ นึกถึงvar opponents = ...
ตัวอย่างของฉัน
นี่คือตัวอย่างของกรณีจริงที่ฉันเคยTuple<>
หลีกเลี่ยงการประกาศชนิดข้อมูลอย่างเดียวเพื่อใช้ภายในแอสเซมบลีของตัวเองเท่านั้น สถานการณ์เกี่ยวข้องกับข้อเท็จจริงที่ว่าเมื่อใช้พจนานุกรมทั่วไปที่มีประเภทที่ไม่ระบุตัวตนมันเป็นการยากที่จะใช้TryGetValue()
วิธีการค้นหารายการในพจนานุกรมเพราะวิธีการนั้นต้องการout
พารามิเตอร์ที่ไม่สามารถตั้งชื่อได้:
public static class DictionaryExt
{
// helper method that allows compiler to provide type inference
// when attempting to locate optionally existent items in a dictionary
public static Tuple<TValue,bool> Find<TKey,TValue>(
this IDictionary<TKey,TValue> dict, TKey keyToFind )
{
TValue foundValue = default(TValue);
bool wasFound = dict.TryGetValue( keyToFind, out foundValue );
return Tuple.Create( foundValue, wasFound );
}
}
public class Program
{
public static void Main()
{
var people = new[] { new { LastName = "Smith", FirstName = "Joe" },
new { LastName = "Sanders", FirstName = "Bob" } };
var peopleDict = people.ToDictionary( d => d.LastName );
// ??? foundItem <= what type would you put here?
// peopleDict.TryGetValue( "Smith", out ??? );
// so instead, we use our Find() extension:
var result = peopleDict.Find( "Smith" );
if( result.First )
{
Console.WriteLine( result.Second );
}
}
}
PSมีอีกวิธีหนึ่ง (เรียบง่าย) ในการแก้ไขปัญหาที่เกิดจากประเภทที่ไม่ระบุชื่อในพจนานุกรมและนั่นคือการใช้var
คำหลักเพื่อให้คอมไพเลอร์ 'อนุมาน' ประเภทสำหรับคุณ นี่คือรุ่นของ:
var foundItem = peopleDict.FirstOrDefault().Value;
if( peopleDict.TryGetValue( "Smith", out foundItem ) )
{
// use foundItem...
}