DotNetSlackers: ASP.NET News for lazy Developers

Tuesday, October 13, 2015

C# Tuple: a multiple component Collection

The general definition of Tuple defines it is an ordered set of data constituting a record.
It is used as data structure or collection to hold data. The good thing is that each value part could be different type. It could be a good substitute for 2 dimensional arrays structure (the reason why I started using it).

I came across to Tuple, when I wanted a collection with pair of values. For example, a similar structure like Dictionary but something like CustomCollection

Before .Net 4.0, the obvious solution would had been to define custom type and use it with a list or array to build the collection.

It is not difficult to create such utility class but when you work on big application and tons of classes are floating around, the initial opinion is to avoid having another custom type and use System classes as much as possible. Coming from the same thought, I ended up using Tuple to build my logic.
Tuple is a System class which provide ways to create a structure to hold almost unlimited values and any type of values.

Each component in Tuple is referred by its sequence number for e.g. Item1, Item2, Item3, Items4 ….
// Tuple structure

http://msdn.microsoft.com/en-us/library/system.tuple.aspx

1
2
3
4
5
6
7
8
9
10
11
public static class Tuple
    {      
      public static Tuple<T1> Create<T1>(T1 item1);       
       public static Tuple<T1, T2> Create<T1, T2>(T1 item1, T2 item2);
       public static Tuple<T1, T2, T3> Create<T1, T2, T3>(T1 item1, T2 item2, T3 item3);
       public static Tuple<T1, T2, T3, T4> Create<T1, T2, T3, T4>(T1 item1, T2 item2, T3 item3, T4 item4);
       public static Tuple<T1, T2, T3, T4, T5> Create<T1, T2, T3, T4, T5>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5);
       public static Tuple<T1, T2, T3, T4, T5, T6> Create<T1, T2, T3, T4, T5, T6>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6);
       public static Tuple<T1, T2, T3, T4, T5, T6, T7> Create<T1, T2, T3, T4, T5, T6, T7>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7);
       public static Tuple<T1, T2, T3, T4, T5, T6, T7, Tuple<T8>> Create<T1, T2, T3, T4, T5, T6, T7, T8>(T1 item1, T2 item2, T3 item3, T4 item4, T5 item5, T6 item6, T7 item7, T8 item8);
    }

tupple structure
Tuple structure
Note the names given to each constructor or to the size of tuple.
For the above definition, you can make out that there are maximum of 8 components that could defined with Tuple. However, Microsoft refers the 8th component as “Rest” property, which allows nesting further tuples to it.  Hence, in a way unlimited tuples could be defined by nesting the each level in Rest property or last component.

The MSDN link to Tuple Class (http://msdn.microsoft.com/en-us/library/system.tuple.aspx ) give few example but limited to only 7 components.

I have a written a small example to give complete picture showing one of the possible reason of using it.

The idea is to give $200 to employees working in non-metro region. There could be many ways to get this problem solved but for sake of simplicity this is best I thought of.
User Interface
Image 1: Shows a Give Misc Payments button and a blank grid view. All the employees in non metro will be given $200 and others will have zero.
  Tupple example grid
When Give Misc Payment button is pressed.



Tupple example grid1
Source code
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace Windows.POC
{
  public partial class TupleTest : Form
  {
    public TupleTest()
    {
      InitializeComponent();
      dataGridView1.DataSource = new List<Employee>();
    }
    ///
<summary>
    /// Fills the data grid view with miscelleneous payments
    /// </summary>
    private void btnMiscPayments_Click(object sender, EventArgs e)
    {
      List<Tuple<string, Employee>> listEmployeeLocation = GetEmployeeWithLocation();
      List<Employee> lstEmployees = new List<Employee>();
      // The idea is to give a $200 to people working in non-metro regions as they have to spend extra time commuting to these places.
      foreach(var t in listEmployeeLocation)
      {
        if(t.Item1 == "Non-Metro")
        {
          t.Item2.MiscPayments = 200;
        }
        else
        {
          t.Item2.MiscPayments = 0;         
        }
         
        lstEmployees.Add(t.Item2);
      }
       
      dataGridView1.DataSource = lstEmployees;
    }
    ///
<summary>
    /// Returns the populated List of employees with their location
    /// </summary>
    private List<Tuple<string, Employee>> GetEmployeeWithLocation()
    {
      List<Tuple<string, Employee>> listEmployeeLocation = new List<Tuple<string, Employee>>();
      // Shorthand for creating and initializing the object with data
      listEmployeeLocation.Add(Tuple.Create("Non-Metro", new Employee { EmpID = 1, FirstName = "Sam", LastName = "Wood", Department = "HR" }));
      listEmployeeLocation.Add(Tuple.Create("Metro", new Employee { EmpID = 2, FirstName = "Mark", LastName = "Will", Department = "Accounts" }));
      listEmployeeLocation.Add(Tuple.Create("Non-Metro", new Employee { EmpID = 3, FirstName = "Julie", LastName = "Diego", Department = "HR" }));
      listEmployeeLocation.Add(Tuple.Create("Metro", new Employee { EmpID =4, FirstName = "Kim", LastName = "Mills", Department = "Finance" }));
      listEmployeeLocation.Add(Tuple.Create("Metro", new Employee { EmpID = 5, FirstName = "Mahir", LastName = "Khan", Department = "IT" }));
      listEmployeeLocation.Add(Tuple.Create("Non-Metro", new Employee { EmpID = 6, FirstName = "Jade", LastName = "Todd", Department = "IT" }));
      return listEmployeeLocation;
    }
  }
  ///
<summary>
  /// Employee entity class
  /// </summary>
  public class Employee
  {
    public Employee()
    { }
    public int EmpID { get; set; }
    public string FirstName { get; set;}
    public string LastName { get; set; }
    public string Department { get; set; }
    public Single MiscPayments { get; set; }
  }
}
The example below uses the 8th components and suggest one of the way of using it.
The 8th or TRest came out as bit an exercise. It was not as straight as I thought it would be. Moreover, the syntax itself turn out be bit lengthy than usual (I am not sure but feel there must be better or clever ways to write it) however, this is what I learnt and presenting you here.
So continuing to same example above, I added 8th item to the EmployeeList. The 8th item is a nested tuple.
1
2
//List with 8th item or nested tuple.
List<Tuple<string, int, string, string, string, string, string, Tuple<string, string>>> listEmployeeTuple = new List<Tuple<string, int, string, string, string, string, string, Tuple<string,string>>>();
Though, I keep saying 8th element but total count of elements in my Tuple is nine, it could also be referred at nintuples similar to Microsoft terminology as specified above.
Tuple example
1
2
3
4
5
6
7
// This one worked -- note the how non-static Tuple class is used
Tuple<string, int, string, string, string, string, string, Tuple<string, string>> firstEmployee = new Tuple<string, int, string, string, string, string, string, Tuple<string, string>>("Non-Metro", 1, "Sam", "Wood", "HR", "8867", "5543789044", new Tuple<string, string>("People Management", "Administration"));
      listEmployeeTuple.Add(firstEmployee);
       
//Another working example with nested tuple created using Static class
Tuple<string, int, string, string, string, string, string, Tuple<string, string>> secondEmployee = new Tuple<string, int, string, string, string, string, string, Tuple<string, string>>("Non-Metro", 1, "Sam", "Wood", "HR", "8867", "5543789044", Tuple.Create("People Management", "Administration"));
      listEmployeeTuple.Add(secondEmployee);
While working on this blog I learnt that there two separate classes defined for Tuples. One is the static class which is ideally used when creating straight 8 non nested octuples.
Other one, a non static, is used when creating more than 8 items or nested tuples similar to what I demonstrated above.
Static Tuple Class Definition
Static Tuple definition
Simple or non static Tuple Class Definition
Non Static Tuple definition
Accessing nested tuples
Accessing nested tuples is an easy part. The Rest property is simply used to get the last element.
1
2
3
4
Tuple<string, int, string, string, string, string, string, Tuple<string, string>> firstEmployee = new Tuple<string, int, string, string, string, string, string, Tuple<string, string>>("Non-Metro", 1, "Sam", "Wood", "HR", "8867", "5543789044", new Tuple<string, string>("People Management", "Administration"));
string primarySkill = firstEmployee.Rest.Item1;
string seondarySkill = firstEmployee.Rest.Item2;
Further nested tuples are accessed by appending Rest to the Rest, in accordance to the number of nests.

For example, 2 nested levels, it will be like
firstEmployee.Rest.Rest.Item1;
I found Tuple a very interesting concept and it helped me quickly write some business logic which would have otherwise lead me to write custom classes.
I don’t claim that all above examples or code or syntax is best way to write code but best to my knowledge and with best intention to share knowledge.
I am sure many coders must have known better or alternate ways to write similar logic. I would be glad to learn all those ways.
Have fun with Tuple.

No comments:

Post a Comment