Ví dụ thực tế nơi Tuple có thể được sử dụng trong .Net 4.0?


97

Tôi đã thấy Tuple được giới thiệu trong .Net 4 nhưng tôi không thể hình dung nó có thể được sử dụng ở đâu. Chúng tôi luôn có thể tạo một lớp Tùy chỉnh hoặc Cấu trúc.


13
Có lẽ đây là một nơi tốt để lưu ý rằng chủ đề này đã rất cũ. Hãy xem điều gì đã xảy ra trong C # 7 !
maf-soft

Câu trả lời:


83

Đó là vấn đề - thuận tiện hơn là không phải lúc nào cũng tạo một lớp hoặc cấu trúc tùy chỉnh. Đó là một cải tiến như Actionhoặc Func... bạn có thể tự tạo các loại này, nhưng thật tiện lợi khi chúng tồn tại trong khuôn khổ.


5
Có lẽ giá trị chỉ ra từ MSDN : "Bất kỳ thành viên public static của loại này là chủ đề an toàn Bất kỳ thành viên dụ không đảm bảo được thread an toàn. "
Matt Borja

Chà, có lẽ các nhà thiết kế ngôn ngữ nên tạo ra các kiểu tùy chỉnh một cách dễ dàng hơn? Vì vậy, chúng tôi có thể giữ cùng một cú pháp thay vì giới thiệu một cú pháp khác?
Thomas Eyde

@ThomasEyde, chính xác là những gì họ đã làm trong 15 năm qua. Đó là cách các thành viên thể hiện trong biểu thức đã được thêm vào và bây giờ là các bộ giá trị. Lớp Ghi kiểu suýt phía sau cắt vào tháng (9 tháng trước khi nhận xét này) cho phiên bản này của C # 7, và có lẽ sắp ra trong C # 8. Cũng lưu ý rằng giá trị các bộ cung cấp giá trị bình đẳng nơi các lớp học đồng bằng tuổi không . Giới thiệu tất cả trở lại đây vào năm 2002 sẽ đòi hỏi sự thấy trước
Panagiotis Kanavos

điều gì làm bạn có ý nghĩa bởi convenient not to make a custom class. Ý bạn là tạo cá thể lớp tùy chỉnh bằng cách sử dụng =new..()?
Alex

75

Với bộ giá trị, bạn có thể dễ dàng triển khai từ điển hai chiều (hoặc n chiều cho vấn đề đó). Ví dụ: bạn có thể sử dụng một từ điển như vậy để triển khai ánh xạ trao đổi tiền tệ:

var forex = new Dictionary<Tuple<string, string>, decimal>();
forex.Add(Tuple.Create("USD", "EUR"), 0.74850m); // 1 USD = 0.74850 EUR
forex.Add(Tuple.Create("USD", "GBP"), 0.64128m);
forex.Add(Tuple.Create("EUR", "USD"), 1.33635m);
forex.Add(Tuple.Create("EUR", "GBP"), 0.85677m);
forex.Add(Tuple.Create("GBP", "USD"), 1.55938m);
forex.Add(Tuple.Create("GBP", "EUR"), 1.16717m);
forex.Add(Tuple.Create("USD", "USD"), 1.00000m);
forex.Add(Tuple.Create("EUR", "EUR"), 1.00000m);
forex.Add(Tuple.Create("GBP", "GBP"), 1.00000m);

decimal result;
result = 35.0m * forex[Tuple.Create("USD", "EUR")]; // USD 35.00 = EUR 26.20
result = 35.0m * forex[Tuple.Create("EUR", "GBP")]; // EUR 35.00 = GBP 29.99
result = 35.0m * forex[Tuple.Create("GBP", "USD")]; // GBP 35.00 = USD 54.58

Tôi muốn sử dụng Enum cho các chữ viết tắt của quốc gia. Điều đó có thể không?
Zack

1
Chắc chắn, nó sẽ hoạt động mà không gặp vấn đề gì vì enums là các loại giá trị.
MarioVW

@MarioVW Nó cũng có thể được thực hiện bằng cách sử dụng mảng đa chiều. Tuple tạo ra sự khác biệt như thế nào?
Alex

26

Có một bài báo xuất sắc trên tạp chí MSDN nói về những cân nhắc về thiết kế và đau bụng khi thêm Tuple vào BCL. Việc lựa chọn giữa kiểu giá trị và kiểu tham chiếu là đặc biệt thú vị.

Như bài báo đã làm rõ, động lực đằng sau Tuple là rất nhiều nhóm bên trong Microsoft đã sử dụng nó, nhóm F #. Mặc dù không được đề cập, tôi nghĩ rằng từ khóa "động" mới trong C # (và VB.NET) cũng có liên quan đến nó, các bộ giá trị rất phổ biến trong các ngôn ngữ động.

Mặt khác, nó không có gì đặc biệt vượt trội so với việc tạo poco của riêng bạn, ít nhất bạn có thể đặt cho các thành viên một cái tên tốt hơn.


CẬP NHẬT: do có một bản sửa đổi lớn trong C # phiên bản 7, bây giờ nhận được nhiều cú pháp hơn. Thông báo sơ bộ trong bài đăng trên blog này .


23

Đây là một ví dụ nhỏ - giả sử bạn có một phương pháp cần tra cứu địa chỉ email và xử lý của người dùng, được cung cấp một Id người dùng. Bạn luôn có thể tạo một lớp tùy chỉnh có chứa dữ liệu đó hoặc sử dụng tham số ref / out cho dữ liệu đó hoặc bạn chỉ có thể trả về Tuple và có một chữ ký phương thức đẹp mà không cần phải tạo POCO mới.

public static void Main(string[] args)
{
    int userId = 0;
    Tuple<string, string> userData = GetUserData(userId);
}

public static Tuple<string, string> GetUserData(int userId)
{
    return new Tuple<string, string>("Hello", "World");
}

10
Tuy nhiên, đây là một ví dụ điển hình, không biện minh cho việc sử dụng Tuple.
Amitabh

7
Một bộ giá trị phù hợp ở đây vì bạn đang trả về các giá trị khác biệt; nhưng một tuple sẽ tỏa sáng hơn khi bạn trả về nhiều giá trị thuộc các loại khác nhau .
Mark Rushakoff,

21
Một ví dụ điển hình khác là int.TryParse, vì bạn có thể loại bỏ tham số đầu ra và thay vào đó sử dụng Tuple. Vì vậy, bạn có thể có Tuple<bool, T> TryParse<T>(string input)và thay vì phải sử dụng một tham số đầu ra, bạn lấy lại cả hai giá trị trong một bộ giá trị.
Tejs

3
trên thực tế, đó chính xác là những gì sẽ xảy ra khi bạn gọi bất kỳ phương thức TryParse nào từ F #.
Joel Mueller,

23

Tôi đã sử dụng một bộ tuple để giải quyết Vấn đề 11 của Project Euler :

class Grid
{
    public static int[,] Cells = { { 08, 02, 22, // whole grid omitted

    public static IEnumerable<Tuple<int, int, int, int>> ToList()
    {
        // code converts grid to enumeration every possible set of 4 per rules
        // code omitted
    }
}

Bây giờ tôi có thể giải quyết toàn bộ vấn đề với:

class Program
{
    static void Main(string[] args)
    {
        int product = Grid.ToList().Max(t => t.Item1 * t.Item2 * t.Item3 * t.Item4);
        Console.WriteLine("Maximum product is {0}", product);
    }
}

Tôi có thể đã sử dụng một loại tùy chỉnh cho điều này, nhưng nó sẽ trông giống hệt như Tuple .


16

Cú pháp tuple của C # rất cồng kềnh, vì vậy các bộ giá trị rất khó khai báo. Và nó không có khớp mẫu, vì vậy chúng cũng khó sử dụng.

Nhưng đôi khi, bạn chỉ muốn một nhóm đối tượng đặc biệt mà không cần tạo một lớp cho nó. Ví dụ: giả sử tôi muốn tổng hợp một danh sách, nhưng tôi muốn hai giá trị thay vì một:

// sum and sum of squares at the same time
var x =
    Enumerable.Range(1, 100)
    .Aggregate((acc, x) => Tuple.Create(acc.Item1 + x, acc.Item2 + x * x));

Thay vì kết hợp một tập hợp các giá trị thành một kết quả, hãy mở rộng một kết quả thành một tập hợp các giá trị. Cách dễ nhất để viết hàm này là:

static IEnumerable<T> Unfold<T, State>(State seed, Func<State, Tuple<T, State>> f)
{
    Tuple<T, State> res;
    while ((res = f(seed)) != null)
    {
        yield return res.Item1;
        seed = res.Item2;
    }
}

fchuyển đổi một số trạng thái thành một tuple. Chúng tôi trả về giá trị đầu tiên từ bộ tuple và đặt trạng thái mới của chúng tôi thành giá trị thứ hai. Điều này cho phép chúng tôi duy trì trạng thái trong suốt quá trình tính toán.

Bạn sử dụng nó như vậy:

// return 0, 2, 3, 6, 8
var evens =
    Unfold(0, state => state < 10 ? Tuple.Create(state, state + 2) : null)
    .ToList();

// returns 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
var fibs =
    Unfold(Tuple.Create(0, 1), state => Tuple.Create(state.Item1, Tuple.Create(state.Item2, state.Item1 + state.Item2)))
    .Take(10).ToList();

evenskhá thẳng thắn, nhưng fibskhôn khéo hơn một chút. Nó statethực sự là một bộ tuple chứa fib (n-2) và fib (n-1) tương ứng.


4
1 Tuple.Create là viết tắt tiện dụng chonew Tuple<Guid,string,...>
AaronLS

@Juliet Việc sử dụng từ khóa State là gì
irfandar

7

Tôi không thích việc lạm dụng chúng, vì chúng tạo ra mã không tự giải thích, nhưng chúng thật tuyệt vời khi triển khai các khóa ghép liên tục, vì chúng triển khai IStructuralEquatable và IStructuralComp so sánh được (để sử dụng cả để tra cứu và sắp xếp mục đích).

Và họ kết hợp tất cả các mã băm của mặt hàng của họ, trong nội bộ; ví dụ, đây là GetHashCode của Tuple (lấy từ ILSpy):

    int IStructuralEquatable.GetHashCode(IEqualityComparer comparer)
    {
        return Tuple.CombineHashCodes(comparer.GetHashCode(this.m_Item1), comparer.GetHashCode(this.m_Item2), comparer.GetHashCode(this.m_Item3));
    }

7

Tuples rất phù hợp để thực hiện nhiều hoạt động IO không đồng bộ cùng một lúc và trả về tất cả các giá trị cùng nhau. Dưới đây là các ví dụ về việc làm điều đó khi có và không có Tuple. Tuples thực sự có thể làm cho mã của bạn rõ ràng hơn!

Không có (làm tổ khó chịu!):

Task.Factory.StartNew(() => data.RetrieveServerNames())
    .ContinueWith(antecedent1 =>
        {
            if (!antecedent1.IsFaulted)
            {
                ServerNames = KeepExistingFilter(ServerNames, antecedent1.Result);
                Task.Factory.StartNew(() => data.RetrieveLogNames())
                    .ContinueWith(antecedent2 =>
                        {
                            if (antecedent2.IsFaulted)
                            {
                                LogNames = KeepExistingFilter(LogNames, antecedent2.Result);
                                Task.Factory.StartNew(() => data.RetrieveEntryTypes())
                                    .ContinueWith(antecedent3 =>
                                        {
                                            if (!antecedent3.IsFaulted)
                                            {
                                                EntryTypes = KeepExistingFilter(EntryTypes, antecedent3.Result);
                                            }
                                        });
                            }
                        });
            }
        });

Với Tuple

Task.Factory.StartNew(() =>
    {
        List<string> serverNames = data.RetrieveServerNames();
        List<string> logNames = data.RetrieveLogNames();
        List<string> entryTypes = data.RetrieveEntryTypes();
        return Tuple.Create(serverNames, logNames, entryTypes);
    }).ContinueWith(antecedent =>
        {
            if (!antecedent.IsFaulted)
            {
                ServerNames = KeepExistingFilter(ServerNames, antecedent.Result.Item1);
                LogNames = KeepExistingFilter(LogNames, antecedent.Result.Item2);
                EntryTypes = KeepExistingFilter(EntryTypes, antecedent.Result.Item3);
            }
        });

Nếu bạn đang sử dụng một chức năng ẩn danh với một loại ngụ ý nào sau đó bạn không thực hiện các mã chưa rõ ràng bằng cách sử dụng các tuple. Đang khôi phục một Tuple từ một phương pháp? Sử dụng một cách tiết kiệm khi sự rõ ràng của mã là chìa khóa, theo ý kiến ​​khiêm tốn của tôi. Tôi biết lập trình hàm trong C # rất khó để chống lại, nhưng chúng ta phải xem xét tất cả những lập trình viên C # "hướng đối tượng" cũ kỹ.


5

Tuples được sử dụng nhiều trong các ngôn ngữ chức năng có thể làm được nhiều việc hơn với chúng, giờ đây F # là ngôn ngữ .net 'chính thức' mà bạn có thể muốn tương tác với nó từ C # và chuyển chúng giữa các mã được viết bằng hai ngôn ngữ.


Tuples cũng được xây dựng trong các kiểu cho một số ngôn ngữ kịch bản phổ biến như Python và Ruby (cũng có triển khai .Net cho interop ... IronPython / Ruby).
MutantNinjaCodeMonkey

5

Tôi có xu hướng tránh Tupleđối với hầu hết các tình huống vì nó ảnh hưởng đến khả năng đọc. Tuy nhiên,Tuple rất hữu ích khi bạn cần nhóm dữ liệu không liên quan.

Ví dụ: giả sử bạn có một danh sách ô tô và các thành phố mà chúng đã được mua:

Mercedes, Seattle
Mustang, Denver
Mercedes, Seattle
Porsche, Seattle
Tesla, Seattle
Mercedes, Seattle

Bạn muốn tổng hợp số lượng cho mỗi ô tô mỗi thành phố:

Mercedes, Seattle [3]
Mustang, Denver [1]
Porsche, Seattle [1]
Tesla, Seattle [1]

Để làm điều này, bạn tạo một Dictionary. Bạn có một vài lựa chọn:

  1. Tạo một Dictionary<string, Dictionary<string, int>>.
  2. Tạo một Dictionary<CarAndCity, int>.
  3. Tạo một Dictionary<Tuple<string, string>, int>.

Khả năng đọc bị mất với tùy chọn đầu tiên. Nó sẽ yêu cầu bạn viết nhiều mã hơn.

Tùy chọn thứ hai hoạt động và ngắn gọn, nhưng xe hơi và thành phố không thực sự liên quan và có thể không thuộc cùng một lớp.

Tùy chọn thứ ba là ngắn gọn và sạch sẽ. Đó là một cách sử dụng tốt Tuple.


4

Một vài ví dụ ngoài ý muốn của tôi:

  • Vị trí X và Y (và Z nếu bạn thích)
  • a Chiều rộng và Chiều cao
  • Mọi thứ được đo lường theo thời gian

Ví dụ: bạn sẽ không muốn bao gồm System.Drawing trong một ứng dụng web chỉ để sử dụng Point / PointF và Size / SizeF.


2
Tuplehữu ích trong các tình huống quan trọng Pointhoặc SomeVectorcó thể hữu ích khi thực hiện các hoạt động đồ họa. Nó làm nổi bật hai giá trị rất ràng buộc với nhau. Tôi thường thấy các thuộc tính có tên StartTime và EndTime khi đọc mã, nhưng thậm chí còn tốt hơn cả ngày giờ và khoảng thời gian, Tuple buộc bạn phải xem xét cả hai giá trị mỗi khi bạn hoạt động trong lĩnh vực logic kinh doanh của mình. Hoặc trả về "hey, dữ liệu đã thay đổi (bool), đây là dữ liệu (loại khác)" được xử lý nặng thay vì đi qua các ràng buộc chuyên sâu.
Léon Pelletier

3

Bạn nên cẩn thận với việc sử dụng Tuplevà có thể suy nghĩ kỹ trước khi làm điều này. Từ kinh nghiệm trước đây của tôi, tôi phát hiện ra rằng việc sử dụng Tuplelàm cho mã rất khó đọc và khó hỗ trợ trong tương lai. Một thời gian trước, tôi đã phải sửa một số mã mà các bộ giá trị được sử dụng hầu như ở khắp mọi nơi. Thay vì nghĩ về các mô hình đối tượng thích hợp, họ chỉ sử dụng các bộ giá trị. Đó là cơn ác mộng ... đôi khi tôi muốn giết người viết mã ...

Tôi không muốn nói rằng bạn không nên sử dụng Tuplevà nó xấu xa hay gì đó và tôi trăm phần trăm chắc chắn rằng có một số nhiệm vụ mà Tupleứng cử viên tốt nhất được sử dụng, nhưng có lẽ bạn nên nghĩ lại, bạn THỰC SỰ cần nó ?


1

Cách sử dụng tốt nhất cho Tuples mà tôi đã tìm thấy là khi cần trả về nhiều hơn 1 loại đối tượng từ một phương thức, bạn biết loại đối tượng và số lượng của chúng, và nó không phải là một danh sách dài.

Các lựa chọn thay thế đơn giản khác sẽ sử dụng tham số 'out'

private string MyMethod(out object)

hoặc làm từ điển

Dictionary<objectType1, objectType2>

Tuy nhiên, sử dụng Tuple sẽ tiết kiệm được việc tạo đối tượng 'out' hoặc về cơ bản phải tra cứu mục nhập trong từ điển;


1

Vừa tìm thấy giải pháp cho một trong những vấn đề của tôi ở Tuple. Nó giống như khai báo một lớp trong phạm vi của một phương thức, nhưng với khai báo lười biếng tên các trường của nó. Bạn thao tác với các bộ sưu tập các bộ giá trị, các thể hiện đơn lẻ của nó và sau đó tạo một bộ sưu tập kiểu ẩn danh với các tên trường bắt buộc, dựa trên bộ giá trị của bạn. Điều này tránh cho bạn tạo lớp mới cho mục đích này.

Nhiệm vụ là viết một phản hồi JSON từ LINQ mà không có bất kỳ lớp bổ sung nào:

 //I select some roles from my ORM my with subrequest and save results to Tuple list
 var rolesWithUsers = (from role in roles
                       select new Tuple<string, int, int>(
                         role.RoleName, 
                         role.RoleId, 
                         usersInRoles.Where(ur => ur.RoleId == role.RoleId).Count()
                      ));

 //Then I add some new element required element to this collection
 var tempResult = rolesWithUsers.ToList();
 tempResult.Add(new Tuple<string, int, int>(
                        "Empty", 
                         -1,
                         emptyRoleUsers.Count()
                      ));

 //And create a new anonimous class collection, based on my Tuple list
 tempResult.Select(item => new
            {
                GroupName = item.Item1,
                GroupId = item.Item2,
                Count = item.Item3
            });


 //And return it in JSON
 return new JavaScriptSerializer().Serialize(rolesWithUsers);

Tất nhiên, chúng tôi có thể làm điều này bằng cách khai báo một Lớp mới cho các nhóm của tôi, nhưng ý tưởng tạo ra một bộ sưu tập nhất trí như vậy mà không cần khai báo các lớp mới.


1

Trong trường hợp của tôi, tôi đã phải sử dụng Tuple khi tôi phát hiện ra rằng chúng tôi không thể sử dụng tham số out trong một phương thức không đồng bộ. Đọc về nó ở đây . Tôi cũng cần một loại trả lại khác. Vì vậy, tôi đã sử dụng Tuple thay thế làm kiểu trả về của mình và đánh dấu phương thức là không đồng bộ.

Mẫu mã bên dưới.

...
...
// calling code.
var userDetails = await GetUserDetails(userId);
Console.WriteLine("Username : {0}", userDetails.Item1);
Console.WriteLine("User Region Id : {0}", userDetails.Item2);
...
...

private async Tuple<string,int> GetUserDetails(int userId)
{
    return new Tuple<string,int>("Amogh",105);
    // Note that I can also use the existing helper method (Tuple.Create).
}

Đọc thêm về Tuple tại đây . Hi vọng điêu nay co ich.


Tôi giả sử bạn không muốn trở về một loại vô danh hoặc Array (hoặc nội dung động)
ozzy432836

0

Thay đổi hình dạng của các đối tượng khi bạn cần gửi chúng qua dây hoặc chuyển đến các lớp ứng dụng khác nhau và nhiều đối tượng được hợp nhất thành một:

Thí dụ:

var customerDetails = new Tuple<Customer, List<Address>>(mainCustomer, new List<Address> {mainCustomerAddress}).ToCustomerDetails();

ExtensionMethod:

public static CustomerDetails ToCustomerDetails(this Tuple<Website.Customer, List<Website.Address>> customerAndAddress)
    {
        var mainAddress = customerAndAddress.Item2 != null ? customerAndAddress.Item2.SingleOrDefault(o => o.Type == "Main") : null;
        var customerDetails = new CustomerDetails
        {
            FirstName = customerAndAddress.Item1.Name,
            LastName = customerAndAddress.Item1.Surname,
            Title = customerAndAddress.Item1.Title,
            Dob = customerAndAddress.Item1.Dob,
            EmailAddress = customerAndAddress.Item1.Email,
            Gender = customerAndAddress.Item1.Gender,
            PrimaryPhoneNo = string.Format("{0}", customerAndAddress.Item1.Phone)
        };

        if (mainAddress != null)
        {
            customerDetails.AddressLine1 =
                !string.IsNullOrWhiteSpace(mainAddress.HouseName)
                    ? mainAddress.HouseName
                    : mainAddress.HouseNumber;
            customerDetails.AddressLine2 =
                !string.IsNullOrWhiteSpace(mainAddress.Street)
                    ? mainAddress.Street
                    : null;
            customerDetails.AddressLine3 =
                !string.IsNullOrWhiteSpace(mainAddress.Town) ? mainAddress.Town : null;
            customerDetails.AddressLine4 =
                !string.IsNullOrWhiteSpace(mainAddress.County)
                    ? mainAddress.County
                    : null;
            customerDetails.PostCode = mainAddress.PostCode;
        }
...
        return customerDetails;
    }

0

Tham số out là tuyệt vời khi chỉ có một vài giá trị cần được trả về, nhưng khi bạn bắt đầu gặp phải 4, 5, 6 hoặc nhiều giá trị cần được trả về, nó có thể trở nên khó sử dụng. Một tùy chọn khác để trả về nhiều giá trị là tạo và trả về một lớp / cấu trúc do người dùng xác định hoặc sử dụng Tuple để đóng gói tất cả các giá trị cần được trả về bởi một phương thức.

Tùy chọn đầu tiên, sử dụng một lớp / cấu trúc để trả về các giá trị, rất đơn giản. Chỉ cần tạo kiểu (trong ví dụ này là một cấu trúc) như sau:

public struct Dimensions
{
public int Height;
public int Width;
public int Depth;
}

Tùy chọn thứ hai, sử dụng Tuple, là một giải pháp thậm chí còn thanh lịch hơn so với sử dụng đối tượng do người dùng xác định. Một Tuple có thể được tạo để chứa bất kỳ số lượng giá trị nào thuộc các loại khác nhau. Ngoài ra, dữ liệu bạn lưu trữ trong Tuple là bất biến; khi bạn thêm dữ liệu vào Tuple thông qua phương thức khởi tạo hoặc phương thức Tạo tĩnh, dữ liệu đó không thể thay đổi được. Tuples có thể chấp nhận tối đa và bao gồm tám giá trị riêng biệt. Nếu bạn cần trả về nhiều hơn tám giá trị, bạn sẽ cần sử dụng lớp Tuple đặc biệt: Lớp Tuple Khi tạo một Tuple có nhiều hơn tám giá trị, bạn không thể sử dụng phương thức Tạo tĩnh — thay vào đó bạn phải sử dụng phương thức khởi tạo của lớp. Đây là cách bạn sẽ tạo một Tuple gồm 10 giá trị số nguyên:

var values = new Tuple<int, int, int, int, int, int, int, Tuple<int, int, int>> (
1, 2, 3, 4, 5, 6, 7, new Tuple<int, int, int> (8, 9, 10));

Tất nhiên, bạn có thể tiếp tục thêm nhiều Tuple vào cuối mỗi Tuple được nhúng, tạo ra bất kỳ kích thước Tuple nào mà bạn cần.


0

Chỉ để tạo mẫu - Tuples là vô nghĩa. Thật tiện lợi khi sử dụng chúng nhưng nó chỉ là một phím tắt! Đối với nguyên mẫu - tốt. Chỉ cần đảm bảo xóa mã này sau.

Nó dễ viết, khó đọc. Nó không có lợi thế rõ ràng so với các lớp, lớp bên trong, lớp ẩn danh, v.v.


0

Tôi đã thử 3 cách để giải quyết vấn đề tương tự trong C # 7 và tôi đã tìm thấy một trường hợp sử dụng cho Tuples.

Làm việc với dữ liệu động trong các dự án web đôi khi có thể khó khăn khi lập bản đồ, v.v.

Tôi thích cách Tuple chỉ tự động ánh xạ vào item1, item2, itemN đối với tôi, điều này có vẻ mạnh mẽ hơn so với việc sử dụng các chỉ mục mảng nơi bạn có thể gặp phải một mục ngoài chỉ mục hoặc sử dụng kiểu ẩn danh nơi bạn có thể viết sai tên thuộc tính.

Có cảm giác như DTO đã được tạo miễn phí chỉ bằng cách sử dụng Tuple và tôi có thể truy cập tất cả các thuộc tính bằng itemN, cảm giác giống như nhập tĩnh hơn mà không cần phải tạo DTO riêng cho mục đích đó.

using System;

namespace Playground
{
    class Program
    {
        static void Main(string[] args)
        {
            var tuple = GetTuple();
            Console.WriteLine(tuple.Item1);
            Console.WriteLine(tuple.Item2);
            Console.WriteLine(tuple.Item3);
            Console.WriteLine(tuple);

            Console.WriteLine("---");

            var dyn = GetDynamic();
            Console.WriteLine(dyn.First);
            Console.WriteLine(dyn.Last);
            Console.WriteLine(dyn.Age);
            Console.WriteLine(dyn);

            Console.WriteLine("---");

            var arr = GetArray();
            Console.WriteLine(arr[0]);
            Console.WriteLine(arr[1]);
            Console.WriteLine(arr[2]);
            Console.WriteLine(arr);

            Console.Read();

            (string, string, int) GetTuple()
            {
                return ("John", "Connor", 1);
            }

            dynamic GetDynamic()
            {
                return new { First = "John", Last = "Connor", Age = 1 };
            }

            dynamic[] GetArray()
            {
                return new dynamic[] { "John", "Connor", 1 };
            }
        }
    }
}
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.