ตั้งแต่ C# 7.3 Tuple รองรับ Structural Equality Comparison — เปรียบเทียบค่าแต่ละ Element แทน Reference
Tuple Syntax (C# 7+)
// Named Tuple Elements
var person1 = (Name: "John", Age: 30, City: "NYC");
var person2 = (Name: "John", Age: 30, City: "NYC");
var person3 = (Name: "Jane", Age: 25, City: "LA");
// Implicit Names (จาก Variable Names)
string name = "John"; int age = 30;
var person4 = (name, age); // (name: "John", age: 30)
Equality Operators (==, !=)
var t1 = (x: 1, y: 2);
var t2 = (x: 1, y: 2);
var t3 = (x: 1, y: 3);
Console.WriteLine(t1 == t2); // True (Values Equal)
Console.WriteLine(t1 == t3); // False (Values Differ)
Console.WriteLine(t1 != t3); // True
Comparison Rules
- Element-wise Comparison (Left-to-Right, Short-circuit)
- Names ไม่สำคัญ — เปรียบเทียบ Position และ Value
- Types ต้อง Compatible (Implicit Conversion Allowed)
- Nested Tuples รองรับ
ตัวอย่างครบถ้วน
using System;
class Demo {
static void Main() {
// Basic Comparison
var a = (x: 1, y: 2);
var b = (p: 1, q: 2); // Different Names, Same Values
Console.WriteLine($"a == b: {a == b}"); // True
// Different Arity (Compile Error in 7.3+, Allowed in 7.0-7.2 with Warning)
// var c = (1, 2, 3);
// Console.WriteLine(a == c); // Error: Tuple Arity Mismatch
// Nested Tuples
var nested1 = (Id: 1, Coords: (X: 10, Y: 20));
var nested2 = (Id: 1, Coords: (X: 10, Y: 20));
Console.WriteLine($"Nested Equal: {nested1 == nested2}"); // True
// With Different Types (Implicit Conversion)
var t1 = (Value: 10, Ratio: 1.5);
var t2 = (Value: 10L, Ratio: 1.5); // long vs int, double vs double
Console.WriteLine($"Mixed Types: {t1 == t2}"); // True (Implicit Conversion)
// Deconstruction for Comparison
var (x1, y1) = a;
var (x2, y2) = b;
Console.WriteLine($"Deconstructed: x1={x1}, y1={y1}");
Console.ReadKey();
}
}
Comparison vs Equals vs Object.ReferenceEquals
| Method | Behavior |
|---|---|
t1 == t2 | Structural Value Equality (Element-wise) |
t1.Equals(t2) | Same as == (ValueTuple Overrides Equals) |
Object.ReferenceEquals(t1, t2) | Always False (ValueTuple is Struct, Stack Allocated) |
Tuple as Dictionary Key
// Tuples เป็น Key ได้เพราะ Implement IEquatable & GetHashCode
var dict = new Dictionary<(int X, int Y), string> {
[(0, 0)] = "Origin",
[(1, 1)] = "Diagonal"
};
Console.WriteLine(dict[(1, 1)]); // "Diagonal"
⚠️ Version Note
- C# 7.0-7.2: Tuple Comparison ต้องการ Name และ Arity ตรงกัน
- C# 7.3+: เปรียบเทียบได้ถ้า Arity และ Types ตรงกัน (Names ไม่สำคัญ)
- C# 7.0:
System.ValueTupleNuGet Package Required (.NET Framework) - .NET Core 2.0+ / .NET Standard 2.0+: Built-in