ตั้งชื่อได้ดีกว่าในคลาส Tuple กว่า“ Item1”,“ Item2”


204

มีวิธีใช้คลาส Tuple แต่ระบุชื่อของรายการในนั้น?

ตัวอย่างเช่น:

public Tuple<int, int, int int> GetOrderRelatedIds()

ที่ส่งคืนรหัสสำหรับ OrderGroupId, OrderTypeId, OrderSubTypeId และ OrderRequirementId

มันจะเป็นการดีถ้าให้ผู้ใช้วิธีการของฉันรู้ว่าอันไหน (เมื่อคุณเรียกใช้เมธอดผลลัพธ์จะเป็นผลลัพธ์Item1, result.Item2, result.Item3, result.Item4 ไม่ชัดเจนว่าจะใช้อันไหน)

(ฉันรู้ว่าฉันสามารถสร้างคลาสเพื่อเก็บรหัสเหล่านี้ทั้งหมดได้ แต่รหัสเหล่านี้มีคลาสของตัวเองที่พวกเขาอาศัยอยู่และสร้างคลาสสำหรับค่าส่งคืนของวิธีนี้ดูเหมือนโง่)


1
คุณจะต้องม้วนตัวเอง - Tupleเป็นเรื่องธรรมดามากดังนั้นนั่นคือทั้งหมดที่คุณจะได้รับ
BrokenGlass

ไม่คุณไม่สามารถทำเช่นนั้นได้โปรดดูที่ลิงก์นี้สำหรับข้อมูลเพิ่มเติมmsdn.microsoft.com/en-us/vcsharp/ee957397
Enigma State

1
ฉันอยากจะบอกว่าการใช้ Tuple เป็นประเภทข้อมูลสาธารณะสำหรับ API ของคุณอาจไม่แนะนำ ฉันมักจะใช้ Tuple สำหรับสิ่งที่อยู่ในระยะสั้นไม่ใช่ค่าตอบแทนของ API
Mike Burdick

1
ลงคะแนนสำหรับคุณสมบัตินี้: visualstudio.uservoice.com/forums/121579-visual-studio-2015/ …
จอห์น

4
มันอยู่ในรายการทำงานของ C # 7 ดูgithub.com/dotnet/roslyn/issues/347
Philip Ding

คำตอบ:


277

ใน C # 7.0 (Visual Studio 2017) มีสิ่งก่อสร้างใหม่ให้ทำดังนี้:

(string first, string middle, string last) LookupName(long id)

68
List<(int first, int second)>ไวยากรณ์ ฉันต้องดาวน์โหลดแพ็คเกจ System.ValueTuple จาก NuGet เพื่อให้สามารถใช้งานได้ใน Visual Studio 2017
Matt Davis

14
เพื่อสร้างมูลค่าreturn (first: first, middle: middle, last: last);
fiat

4
หรือเฉพาะ: return (first, middle, last);ใน. NET 4.7.1 (ไม่แน่ใจสำหรับ 4.7.0)
watbywbarif

1
ในการใช้งานคุณจะต้องเพิ่มแพ็กเกจ System.ValueTuple nuget
Alex G

11
ควรสังเกตว่าของ C # 7 ValueTupleในขณะที่มักจะดีเป็นประเภทค่าที่ไม่แน่นอน (struct) ในขณะที่Tupleเป็นประเภทอ้างอิงที่ไม่เปลี่ยนรูป (คลาส) เท่าที่ฉันรู้ไม่มีวิธีที่จะได้รับประเภทอ้างอิงที่Tupleมีชื่อรายการที่เป็นมิตร
dx_over_dt

51

จนถึง C # 7.0 ไม่มีวิธีที่จะกำหนดประเภทของคุณเอง


13
ฉันไม่อยากเชื่อเลยว่าคำตอบนี้ได้รับการยอมรับด้วยคะแนน 40 คุณอาจมีอย่างน้อยแสดงให้เห็นว่าคลาสที่มีตัวสร้างที่เหมาะสมสามารถแทนที่สิ่งนี้ได้อย่างไร
bytecode77

1
@ bytecode77 เร็ว ๆ นี้คำตอบนี้จะผิดไป: github.com/dotnet/roslyn/issues/347
MarkPflug

ฉันเห็นข้อเสนอเทศกาลภาษาเหล่านี้แล้ว แต่จนถึงขณะนี้คลาสเป็นทางออกที่เหมาะสมสำหรับประเภทข้อมูลที่ซับซ้อนมากขึ้น ทำไมคุณต้องการบังคับให้ใช้ Tuples ไม่ว่าจะเกิดอะไรขึ้น (ดูคำตอบอื่น ๆ )
bytecode77

3
หลังจากเปิดตัว C # 7 แล้วคุณสามารถทำได้เช่นนี้: msdn.microsoft.com/en-us/magazine/mt595758.aspx
Burak Karakuş

11
Q 'มีแท็ก c # 4 ดังนั้นแม้ว่าคำตอบสั้น ๆ แต่ก็ยังถูกต้อง
Steve Drake

33

นี่เป็นเวอร์ชั่นที่ซับซ้อนเกินกว่าที่คุณจะขอ:

class MyTuple : Tuple<int, int>
{
    public MyTuple(int one, int two)
        :base(one, two)
    {

    }

    public int OrderGroupId { get{ return this.Item1; } }
    public int OrderTypeId { get{ return this.Item2; } }

}

ทำไมไม่เพียงแค่ทำการเรียน?


2
struct จะดีกว่าในกรณีนี้แทนที่จะเป็น Class หรือไม่
deathrace

5
ข้อได้เปรียบเล็กน้อยที่ฉันเห็นคือมันใช้ตัวดำเนินการเท่ากับโดยอัตโนมัติตรวจสอบว่าอินสแตนซ์ 2 ตัวเท่ากันถ้ารายการเท่ากันทั้งหมด
JSoet

8
ข้อเสียเปรียบอีกวิธีหนึ่งคือ Item1 และ Item2 ยังคงเป็นคุณสมบัติสาธารณะใน MyTuple
RJFalconer

3
@deathrace Tuple เป็นคลาสดังนั้นหากคุณต้องการรับมรดกโดยตรงจากTuple<T, T2>คุณไม่สามารถเป็น struct ได้
Chakrava

3
ผมอาจจะผิด แต่ผมส่วนใหญ่ใช้ tuple ใดก็ตามที่ฉันต้องการที่จะกลับวัตถุ แต่ไม่ต้องการที่จะกำหนดระดับที่เฉพาะเจาะจง ..
เจย์

12

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

class Program
{
    static void Main(string[] args)
    {
        dynamic employee, manager;

        employee = new ExpandoObject();
        employee.Name = "John Smith";
        employee.Age = 33;

        manager = new ExpandoObject();
        manager.Name = "Allison Brown";
        manager.Age = 42;
        manager.TeamSize = 10;

        WritePerson(manager);
        WritePerson(employee);
    }
    private static void WritePerson(dynamic person)
    {
        Console.WriteLine("{0} is {1} years old.",
                          person.Name, person.Age);
        // The following statement causes an exception
        // if you pass the employee object.
        // Console.WriteLine("Manages {0} people", person.TeamSize);
    }
}
// This code example produces the following output:
// John Smith is 33 years old.
// Allison Brown is 42 years old.

สิ่งอื่นที่ควรค่าแก่การกล่าวถึงคือประเภทที่ไม่ระบุชื่อ สำหรับวิธีการหนึ่ง แต่คุณต้องสร้างคลาสหากคุณต้องการส่งคืนคลาส

var MyStuff = new
    {
        PropertyName1 = 10,
        PropertyName2 = "string data",
        PropertyName3 = new ComplexType()
    };

10

ทำซ้ำคำตอบของฉันจากโพสต์นี้เพราะมันเป็นแบบที่ดีกว่าที่นี่

เริ่มต้น C # v7.0 ตอนนี้มันเป็นไปได้ที่จะตั้งชื่อคุณสมบัติ tuple ซึ่งก่อนหน้านี้ใช้ในการเริ่มต้นกับชื่อที่กำหนดไว้ล่วงหน้าเช่นItem1, Item2และอื่น ๆ

การตั้งชื่อคุณสมบัติของ Tuple Literals :

var myDetails = (MyName: "RBT_Yoga", MyAge: 22, MyFavoriteFood: "Dosa");
Console.WriteLine($"Name - {myDetails.MyName}, Age - {myDetails.MyAge}, Passion - {myDetails.MyFavoriteFood}");

ผลลัพธ์บนคอนโซล:

ชื่อ - RBT_Yoga อายุ - 22 ความหลงใหล - Dosa

กลับ Tuple (มีคุณสมบัติชื่อ) จากวิธีการ :

static void Main(string[] args)
{
    var empInfo = GetEmpInfo();
    Console.WriteLine($"Employee Details: {empInfo.firstName}, {empInfo.lastName}, {empInfo.computerName}, {empInfo.Salary}");
}

static (string firstName, string lastName, string computerName, int Salary) GetEmpInfo()
{
    //This is hardcoded just for the demonstration. Ideally this data might be coming from some DB or web service call
    return ("Rasik", "Bihari", "Rasik-PC", 1000);
}

ผลลัพธ์บนคอนโซล:

รายละเอียดพนักงาน: Rasik, Bihari, Rasik-PC, 1,000

การสร้างรายการ Tuples ที่มีคุณสมบัติชื่อ

var tupleList = new List<(int Index, string Name)>
{
    (1, "cow"),
    (5, "chickens"),
    (1, "airplane")
};

foreach (var tuple in tupleList)
    Console.WriteLine($"{tuple.Index} - {tuple.Name}");

เอาต์พุตบนคอนโซล:

1 - วัว 5 - ไก่ 1 - เครื่องบิน

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

หมายเหตุ : ข้อมูลโค้ดของฉันจะใช้คุณลักษณะการแก้ไขสตริงของ C # v7 ตามรายละเอียดที่นี่


3

MichaelMocko ตอบแล้วดีมาก

แต่ฉันต้องการเพิ่มบางสิ่งที่ฉันต้องคิดออก

(string first, string middle, string last) LookupName(long id)

ด้านบนบรรทัดจะทำให้คุณรวบรวมข้อผิดพลาดเวลาถ้าคุณใช้. net framework <4.7

ดังนั้นหากคุณมีโครงการที่ใช้. net framework <4.7และคุณยังต้องการใช้ ValueTuple กว่า workAround ก็จะติดตั้งแพ็คเกจ nuget นี้



2

หากประเภทรายการของคุณแตกต่างกันทั้งหมดนี่คือชั้นเรียนที่ฉันทำเพื่อให้พวกเขาเข้าใจง่ายขึ้น

การใช้งานของชั้นนี้:

var t = TypedTuple.Create("hello", 1, new MyClass());
var s = t.Get<string>();
var i = t.Get<int>();
var c = t.Get<MyClass>();

รหัสแหล่งที่มา:

public static class TypedTuple
{
    public static TypedTuple<T1> Create<T1>(T1 t1)
    {
        return new TypedTuple<T1>(t1);
    }

    public static TypedTuple<T1, T2> Create<T1, T2>(T1 t1, T2 t2)
    {
        return new TypedTuple<T1, T2>(t1, t2);
    }

    public static TypedTuple<T1, T2, T3> Create<T1, T2, T3>(T1 t1, T2 t2, T3 t3)
    {
        return new TypedTuple<T1, T2, T3>(t1, t2, t3);
    }

    public static TypedTuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 t1, T2 t2, T3 t3, T4 t4)
    {
        return new TypedTuple<T1, T2, T3, T4>(t1, t2, t3, t4);
    }

    public static TypedTuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5)
    {
        return new TypedTuple<T1, T2, T3, T4, T5>(t1, t2, t3, t4, t5);
    }

    public static TypedTuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6)
    {
        return new TypedTuple<T1, T2, T3, T4, T5, T6>(t1, t2, t3, t4, t5, t6);
    }

    public static TypedTuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7)
    {
        return new TypedTuple<T1, T2, T3, T4, T5, T6, T7>(t1, t2, t3, t4, t5, t6, t7);
    }

    public static TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 t1, T2 t2, T3 t3, T4 t4, T5 t5, T6 t6, T7 t7, T8 t8)
    {
        return new TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8>(t1, t2, t3, t4, t5, t6, t7, t8);
    }

}

public class TypedTuple<T>
{
    protected Dictionary<Type, object> items = new Dictionary<Type, object>();

    public TypedTuple(T item1)
    {
        Item1 = item1;
    }

    public TSource Get<TSource>()
    {
        object value;
        if (this.items.TryGetValue(typeof(TSource), out value))
        {
            return (TSource)value;
        }
        else
            return default(TSource);
    }

    private T item1;
    public T Item1 { get { return this.item1; } set { this.item1 = value; this.items[typeof(T)] = value; } }
}

public class TypedTuple<T1, T2> : TypedTuple<T1>
{
    public TypedTuple(T1 item1, T2 item2)
        : base(item1)
    {
        Item2 = item2;
    }

    private T2 item2;
    public T2 Item2 { get { return this.item2; } set { this.item2 = value; this.items[typeof(T2)] = value; } }
}

public class TypedTuple<T1, T2, T3> : TypedTuple<T1, T2>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3)
        : base(item1, item2)
    {
        Item3 = item3;
    }

    private T3 item3;
    public T3 Item3 { get { return this.item3; } set { this.item3 = value; this.items[typeof(T3)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4> : TypedTuple<T1, T2, T3>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4)
        : base(item1, item2, item3)
    {
        Item4 = item4;
    }

    private T4 item4;
    public T4 Item4 { get { return this.item4; } set { this.item4 = value; this.items[typeof(T4)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4, T5> : TypedTuple<T1, T2, T3, T4>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5)
        : base(item1, item2, item3, item4)
    {
        Item5 = item5;
    }

    private T5 item5;
    public T5 Item5 { get { return this.item5; } set { this.item5 = value; this.items[typeof(T5)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4, T5, T6> : TypedTuple<T1, T2, T3, T4, T5>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6)
        : base(item1, item2, item3, item4, item5)
    {
        Item6 = item6;
    }

    private T6 item6;
    public T6 Item6 { get { return this.item6; } set { this.item6 = value; this.items[typeof(T6)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4, T5, T6, T7> : TypedTuple<T1, T2, T3, T4, T5, T6>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7)
        : base(item1, item2, item3, item4, item5, item6)
    {
        Item7 = item7;
    }

    private T7 item7;
    public T7 Item7 { get { return this.item7; } set { this.item7 = value; this.items[typeof(T7)] = value; } }
}

public class TypedTuple<T1, T2, T3, T4, T5, T6, T7, T8> : TypedTuple<T1, T2, T3, T4, T5, T6, T7>
{
    public TypedTuple(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8)
        : base(item1, item2, item3, item4, item5, item6, item7)
    {
        Item8 = item8;
    }

    private T8 item8;
    public T8 Item8 { get { return this.item8; } set { this.item8 = value; this.items[typeof(T8)] = value; } }
}

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

และขอพระเจ้าทรงเมตตาจิตวิญญาณของคุณ
Jamie M.

1

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

Tuple<ApiResource, JSendResponseStatus> result = await SendApiRequest();
ApiResource apiResource = result.Item1;
JSendResponseStatus jSendStatus = result.Item2;

0

ฉันคิดว่าฉันจะสร้างคลาส แต่อีกทางเลือกหนึ่งคือพารามิเตอร์เอาต์พุต

public void GetOrderRelatedIds(out int OrderGroupId, out int OrderTypeId, out int OrderSubTypeId, out int OrderRequirementId)

เนื่องจาก Tuple ของคุณมีจำนวนเต็มคุณจึงสามารถใช้แทน a ได้ Dictionary<string,int>

var orderIds = new Dictionary<string, int> {
    {"OrderGroupId", 1},
    {"OrderTypeId", 2},
    {"OrderSubTypeId", 3},
    {"OrderRequirementId", 4}.
};

แต่ฉันไม่แนะนำเช่นนั้น


0

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

มันเป็นเรื่องของความสมดุล ...

ดูเหมือนว่าปัญหาของคุณจะเป็นสิ่งที่คุณต้องการเรียน และเพื่อความสมบูรณ์คลาสนี้ด้านล่างนี้ยังมีตัวสร้าง


นี่คือรูปแบบที่เหมาะสมสำหรับ

  • ชนิดข้อมูลที่กำหนดเอง
    • โดยไม่มีฟังก์ชั่นเพิ่มเติม Getters และ setters ยังสามารถขยายด้วยรหัสรับ / ตั้งค่าสมาชิกส่วนตัวด้วยรูปแบบชื่อของ "_orderGroupId" ในขณะที่ยังดำเนินการรหัสการทำงาน
  • รวมถึงคอนสตรัคเตอร์ นอกจากนี้คุณยังสามารถเลือกที่จะรวมเพียงหนึ่งคอนสตรัคถ้าคุณสมบัติทั้งหมดเป็นสิ่งจำเป็น
  • หากคุณต้องการใช้ Constructor ทั้งหมดการทำฟองสบู่แบบนี้เป็นรูปแบบที่เหมาะสมเพื่อหลีกเลี่ยงรหัสที่ซ้ำกัน

public class OrderRelatedIds
{
    public int OrderGroupId { get; set; }
    public int OrderTypeId { get; set; }
    public int OrderSubTypeId { get; set; }
    public int OrderRequirementId { get; set; }

    public OrderRelatedIds()
    {
    }
    public OrderRelatedIds(int orderGroupId)
        : this()
    {
        OrderGroupId = orderGroupId;
    }
    public OrderRelatedIds(int orderGroupId, int orderTypeId)
        : this(orderGroupId)
    {
        OrderTypeId = orderTypeId;
    }
    public OrderRelatedIds(int orderGroupId, int orderTypeId, int orderSubTypeId)
        : this(orderGroupId, orderTypeId)
    {
        OrderSubTypeId = orderSubTypeId;
    }
    public OrderRelatedIds(int orderGroupId, int orderTypeId, int orderSubTypeId, int orderRequirementId)
        : this(orderGroupId, orderTypeId, orderSubTypeId)
    {
        OrderRequirementId = orderRequirementId;
    }
}

หรือถ้าคุณต้องการมันง่ายจริงๆ: คุณยังสามารถใช้ initializers ประเภท:

OrderRelatedIds orders = new OrderRelatedIds
{
    OrderGroupId = 1,
    OrderTypeId = 2,
    OrderSubTypeId = 3,
    OrderRequirementId = 4
};

public class OrderRelatedIds
{
    public int OrderGroupId;
    public int OrderTypeId;
    public int OrderSubTypeId;
    public int OrderRequirementId;
}

0

ฉันจะเขียนชื่อรายการในซัมมิท .. ดังนั้นโดยการวางเมาส์ไว้เหนือฟังก์ชั่น helloworld () ข้อความจะกล่าวว่า hello = Item1 และ world = Item2

 helloworld("Hi1,Hi2");

/// <summary>
/// Return hello = Item1 and world Item2
/// </summary>
/// <param name="input">string to split</param>
/// <returns></returns>
private static Tuple<bool, bool> helloworld(string input)
{
    bool hello = false;
    bool world = false;
    foreach (var hw in input.Split(','))
    {
        switch (hw)
        {
            case "Hi1":
                hello= true;
                break;
            case "Hi2":
                world= true;
                break;
        }

    }
    return new Tuple<bool, bool>(hello, world);
}

0

เพียงเพิ่มคำตอบของ @MichaelMocko Tuples มี gotchas สองสามในขณะนี้:

คุณไม่สามารถใช้พวกมันในต้นไม้แสดงอารมณ์ของ EF

ตัวอย่าง:

public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        // Selecting as Tuple
        .Select(person => (person.Name, person.Surname))
        .First();
}

สิ่งนี้จะล้มเหลวในการคอมไพล์ด้วย "ทรีนิพจน์อาจไม่มีข้อผิดพลาด tuple" น่าเสียดายที่นิพจน์ต้นไม้ API นั้นไม่ได้รับการสนับสนุนจากสิ่งอันดับเมื่อเพิ่มสิ่งเหล่านี้ลงในภาษา

ติดตาม (และโหวตขึ้น) ปัญหานี้สำหรับการอัปเดต: https://github.com/dotnet/roslyn/issues/12897

หากต้องการแก้ไขปัญหาคุณสามารถแปลงเป็นประเภทไม่ระบุชื่อก่อนจากนั้นแปลงค่าเป็น tuple:

// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => new { person.Name, person.Surname })
        .ToList()
        .Select(person => (person.Name, person.Surname))
        .First();
}

ตัวเลือกอื่นคือการใช้ ValueTuple.Create:

// Will work
public static (string name, string surname) GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => ValueTuple.Create(person.Name, person.Surname))
        .First();
}

อ้างอิง:

คุณไม่สามารถแยกพวกมันออกเป็น lambdas ได้

มีข้อเสนอเพื่อเพิ่มการสนับสนุน: https://github.com/dotnet/csharplang/issues/258

ตัวอย่าง:

public static IQueryable<(string name, string surname)> GetPersonName(this PersonContext ctx, int id)
{
    return ctx.Persons
        .Where(person => person.Id == id)
        .Select(person => ValueTuple.Create(person.Name, person.Surname));
}

// This won't work
ctx.GetPersonName(id).Select((name, surname) => { return name + surname; })

// But this will
ctx.GetPersonName(id).Select(t => { return t.name + t.surname; })

อ้างอิง:

พวกมันจะไม่ทำให้เป็นอนุกรม

using System;
using Newtonsoft.Json;

public class Program
{
    public static void Main() {
        var me = (age: 21, favoriteFood: "Custard");
        string json = JsonConvert.SerializeObject(me);

        // Will output {"Item1":21,"Item2":"Custard"}
        Console.WriteLine(json); 
    }
}

ชื่อฟิลด์ Tuple มีให้เฉพาะในเวลาคอมไพล์และจะถูกลบออกตอนรันไทม์

อ้างอิง:


-1

คุณสามารถเขียนคลาสที่มี Tuple

คุณต้องแทนที่ฟังก์ชัน Equals และ GetHashCode

และตัวดำเนินการ == และ! =

class Program
{
    public class MyTuple
    {
        private Tuple<int, int> t;

        public MyTuple(int a, int b)
        {
            t = new Tuple<int, int>(a, b);
        }

        public int A
        {
            get
            {
                return t.Item1;
            }
        }

        public int B
        {
            get
            {
                return t.Item2;
            }
        }

        public override bool Equals(object obj)
        {
            return t.Equals(((MyTuple)obj).t);
        }

        public override int GetHashCode()
        {
            return t.GetHashCode();
        }

        public static bool operator ==(MyTuple m1, MyTuple m2)
        {
            return m1.Equals(m2);
        }

        public static bool operator !=(MyTuple m1, MyTuple m2)
        {
            return !m1.Equals(m2);
        }
    }

    static void Main(string[] args)
    {
        var v1 = new MyTuple(1, 2);
        var v2 = new MyTuple(1, 2);

        Console.WriteLine(v1 == v2);

        Dictionary<MyTuple, int> d = new Dictionary<MyTuple, int>();
        d.Add(v1, 1);

        Console.WriteLine(d.ContainsKey(v2));
    }
}

จะกลับมา:

จริง

จริง


2
หากคุณใช้คลาสสำหรับชนิดข้อมูลนี้อยู่แล้วเหตุใดคุณจึงประกาศ Tuple สำหรับข้อมูลพื้นฐานแทนที่จะเป็นเพียงคุณสมบัติ
bytecode77

ฉันต้องการใช้คุณลักษณะ tuple ที่มันเรียบเรียงโดยค่าในฟังก์ชัน Equals
ss

นั่นอาจเป็นโบนัส แต่ในทางกลับกันคุณได้สร้างคลาสที่มีคุณสมบัติที่มีตั้งแต่ Item1 ถึง ItemX ฉันจะเลือกการตั้งชื่อที่เหมาะสมและรหัสเพิ่มเติมใน Equals () มากกว่าโดยใช้ tuple
bytecode77

-1

ตัวอย่าง tuple C # 7

var tuple = TupleExample(key, value);

     private (string key1, long value1) ValidateAPIKeyOwnerId(string key, string value)
            {
                return (key, value);
            }
      if (!string.IsNullOrEmpty(tuple.key1) && tuple.value1 > 0)
          {
                    //your code

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