Practical example where Tuple can be used in .Net 4.0?

后端 未结 19 654
后悔当初
后悔当初 2020-12-04 07:44

I have seen the Tuple introduced in .Net 4 but I am not able to imagine where it can be used. We can always make a Custom class or Struct.

相关标签:
19条回答
  • 2020-12-04 08:02

    An out parameter is great when there are only a few values that need to be returned, but when you start encountering 4, 5, 6, or more values that need to be returned, it can get unwieldy. Another option for returning multiple values is to create and return a user-defined class/structure or to use a Tuple to package up all the values that need to be returned by a method.

    The first option, using a class/structure to return the values, is straightforward. Just create the type (in this example it is a structure) like so:

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

    The second option, using a Tuple, is an even more elegant solution than using a userdefined object. A Tuple can be created to hold any number of values of varying types. In addition, the data you store in the Tuple is immutable; once you add the data to the Tuple through the constructor or the static Create method, that data cannot be changed. Tuples can accept up to and including eight separate values. If you need to return more than eight values, you will need to use the special Tuple class: Tuple Class When creating a Tuple with more than eight values, you cannot use the static Create method—you must instead use the constructor of the class. This is how you would create a Tuple of 10 integer values:

    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));
    

    Of course, you can continue to add more Tuples to the end of each embedded Tuple, creating any size Tuple that you need.

    0 讨论(0)
  • 2020-12-04 08:04

    The best use for Tuples I have found is when needing to return more than 1 type of object from a method, you know what object types and number they will be, and it is not a long list.

    Other simple alternatives would be using an 'out' parameter

    private string MyMethod(out object)
    

    or making a Dictionary

    Dictionary<objectType1, objectType2>
    

    Using a Tuple however saves either creating the 'out' object or having to essentially look-up the entry in the dictionary;

    0 讨论(0)
  • 2020-12-04 08:04

    Well I tried 3 ways to solve the same problem in C#7 and I have found a use case for Tuples.

    Working with dynamic data in web projects can sometimes be a pain when mapping etc.

    I like the way the Tuple just auto mapped onto item1, item2, itemN which seems more robust to me than using array indexes where you might get caught on an out of index item or using the anonymous type where you may misspell a property name.

    It feels like a DTO has been created for free just by using a Tuple and I can access all the properties using itemN which feels more like static typing without having to create a separate DTO for that purpose.

    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 };
                }
            }
        }
    }
    
    0 讨论(0)
  • 2020-12-04 08:05

    Here's a small example - say you have a method that needs to lookup a user's handle and email address, given a user Id. You can always make a custom class that contains that data, or use a ref / out parameter for that data, or you can just return a Tuple and have a nice method signature without having to create a new POCO.

    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");
    }
    
    0 讨论(0)
  • 2020-12-04 08:05

    Changing shapes of objects when you need to send them across wire or pass to different layer of application and multiple objects get merged into one:

    Example:

    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 讨论(0)
  • 2020-12-04 08:07

    Well in my case, I had to use a Tuple when I found out that we cannot use out parameter in an asynchronous method. Read about it here. I also needed a different return type. So I used a Tuple instead as my return type and marked the method as async.

    Sample code below.

    ...
    ...
    // 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).
    }
    

    Read more about Tuple here. Hope this helps.

    0 讨论(0)
提交回复
热议问题