.NET 4 – System.Tuple vs Anonymous Type

3d tuple.Net 4.0 cho ra mắt một nhóm class mới với cùng tên là Tuple. Mục đích của các class là tạo một đối tượng lưu trữ cho các dữ liệu phức tạp, và nhờ đó người dùng khỏi cần phải tạo thêm một class mới. Nhưng từ .Net 3, bạn đã có thể sử dụng anonymous type để làm điều này với cú pháp đơn giản hơn. Vậy thì System.Tuple phải chăng là dư thừa?

Tuple là gì?

.Net 4 cung cấp cho người dùng 8 class generic Tuple<> và một static class Tuple để tạo ra các thể hiện của mỗi class Tuple<> tương ứng với phương thức Tuple.Create(). Mỗi class Tuple<> đã được định nghĩa sẵn các property có tên là Item1, Item2, Item3,… dựa vào số lượng tham số của constructor.
Lưu ý rằng các property phải được gán giá trị thông qua constructor vì nó chỉ cho phép bạn lấy giá trị (read only).

public class Tuple <T1>
public class Tuple <T1, T2>
public class Tuple <T1, T2, T3>
public class Tuple <T1, T2, T3, T4>
public class Tuple <T1, T2, T3, T4, T5>
public class Tuple <T1, T2, T3, T4, T5, T6>
public class Tuple <T1, T2, T3, T4, T5, T6, T7>
public class Tuple <T1, T2, T3, T4, T5, T6, T7, TRest>

3d tuple
Công dụng của class này là để bạn khỏi phải tạo các class để lưu trữ các kiểu dữ liệu phức tạp và tạm thời. Một giải pháp khác là dùng mảng object[] để lưu dữ liệu nhưng điều này ảnh hưởng tới hiệu suất thực thi do phải thực hiện chuyển đổi kiểu. Với Tuple, bạn có thể xác định bất kì kiểu tham số nào cần khởi tạo:

static void Main(string[] args)
{
    var t1 = new Tuple<int, string, bool>(1234, "Hello World",true);
    Console.WriteLine(t1.Item1 * 2);         // 246
    Console.WriteLine(t1.Item2.ToUpper());   // HELLO WORLD
    Console.WriteLine(t1.Item3?"One":"Two"); // One

    Console.ReadKey();
}

Một điểm nữa là các Tuple có thể so sánh với nhau bằng phương thức Equals() bằng cách dựa vào từng property của chúng. Việc so sánh không chỉ dựa vào dữ liệu của các property mà còn dựa vào thứ tự của chúng:

static void Main(string[] args)
{
    var t1 = new Tuple<int, string, bool>(1234, "Hello World", true);
    var t2 = new Tuple<int, string, bool>(1234, "Hello World", true);
    var t3 = new Tuple<int, bool, string>(1234, true, "Hello World");
    Console.WriteLine(t1.Equals(t2));   // True
    Console.WriteLine(t1.Equals(t3));   // False

    Console.ReadKey();
}

Anonymous Type làm được không?

Hãy thử lại ví dụ đầu tiên với anonymous type, nó không chỉ linh hoạt hơn trong việc cho phép người dùng xác định số lượng tham số mà còn có thể đặt tên bất kì cho các tham số:

static void Main(string[] args)
{
    var a1 = new { Item100 = 1234, Item200 = "Hello World", Item300 = true };
    Console.WriteLine(a1.Item100 * 2);            // 246
    Console.WriteLine(a1.Item200.ToUpper());      // HELLO WORLD
    Console.WriteLine(a1.Item300 ? "One" : "Two"); // One

    Console.ReadKey();
}

Anonymous có so sánh được không? Tất nhiên là được, nhưng nó vẫn phụ thuộc vào tên của property và thứ tự các tham số:

static void Main(string[] args)
{
    var a1 = new { A = 1234, B = "Hello World", C = true };
    var a2 = new { A = 1234, B = "Hello World", C = true };
    var a3 = new { A = 1234, C = true, B = "Hello World", };

    Console.WriteLine(a1.Equals(a2));  // True
    Console.WriteLine(a1.Equals(a3));  // False

    Console.ReadKey();
}

“Vậy tôi có cần đến Tuple?”

Câu trả lời là: Tôi không chắc. Điều này thực sự có thể gây một số tranh cãi nhưng cá nhân tôi cho rằng có thể class này sẽ không cần thiết (được thay thế bởi một kĩ thuật khác).
Đối với bạn, có thể câu trả lời là:
Không: Chỉ cần sử dụng anonymous type là đủ.
Có: Sử dụng Tuple để tạo đối tượng sẽ an toàn hơn anonymous type. Lý do là bạn bị áp đặt sử dụng các tên property cố định. Mặc dù điều này làm cho thông tin của các đối tượng thiếu rõ ràng hơn so với các anonymouse object. Tuy nhiên chúng đảm bảo rằng các đối tượng sẽ được so sánh chính xác hơn.
Trong một ví dụ nho nhỏ, bạn có thể tạo một class MyObject như sau:

class MyObject : Tuple<int, string, bool>
{
    public MyObject(int item1, string item2, bool item3) :
        base(item1, item2, item3) { }
}

class Program
{
    static void Main(string[] args)
    {

        var obj1 = new MyObject(1234, "Hello World", true);
        var obj2 = new MyObject(1234, "Hello World", true);
        Console.WriteLine(obj1.Equals(obj2));  // True

        Console.ReadKey();
    }
}

Điều này giúp giảm bớt việc phải khai báo các property và vẫn có so sánh được các đối tượng với nhau dựa vào phương thức Equals(). Tuy nhiên hạn chế của nó là không thể thay đổi được các giá trị của property như đã nói ở phần đầu.
Một vấn đề nữa là khi làm việc các class generic khác, bạn ko thể dùng được anonymous type. Ví dụ như một List<T>, bạn có thể đặt Tuple<> vào (List<Tuple<>>) thay vì tạo một class mới.

Cuối cùng là …

Bài này tôi viết chỉ có mục đích giới thiệu về class Tuple và nhân tiện nhắc lại về anonymous type. Trong thực tế, ít ai biết về class này, và cho dù có biết thì có lẽ đa số họ cũng không quan tâm đến.
Đối với tôi thì chưa bao giờ sử dụng đến class này khi viết chương trình. Tuy nhiên có thể có những ứng dụng hữu ích của class này mà tôi không biết.

https://yinyangit.wordpress.com

Advertisements

5 thoughts on “.NET 4 – System.Tuple vs Anonymous Type

  1. 01 static void Main(string[] args)
    02 {
    03 var t1 = new Tuple(1234, “Hello World”, true);
    04 var t2 = new Tuple(1234, “Hello World”, true);
    05 var t3 = new Tuple(1234, true, “Hello World”);
    06 Console.WriteLine(t1.Equals(t2)); // True
    07 Console.WriteLine(t1.Equals(t3)); // True
    08
    09 Console.ReadKey();
    10 }

    Dòng thứ 07 kết quả là False bạn nhé 🙂

    Phản hồi
  2. Pingback: .NET 4 – System.Tuple vs Anonymous Type | itdzom

Trả lời

Mời bạn điền thông tin vào ô dưới đây hoặc kích vào một biểu tượng để đăng nhập:

WordPress.com Logo

Bạn đang bình luận bằng tài khoản WordPress.com Log Out / Thay đổi )

Twitter picture

Bạn đang bình luận bằng tài khoản Twitter Log Out / Thay đổi )

Facebook photo

Bạn đang bình luận bằng tài khoản Facebook Log Out / Thay đổi )

Google+ photo

Bạn đang bình luận bằng tài khoản Google+ Log Out / Thay đổi )

Connecting to %s