@BrCAEefArBABEBAsEfCAXWC| G78465545VCWBC~B G58496VCB 5784VC~~BPW~ G5746466VCPWBWP-~BCC 5454549VCBC 56456VCY 68777VCB~ 5688888845688884568888456888846F858458545-~~~~WCXB

Tuple.` From the mountain's peak to the ocean's floor, look around the world. Snow, on the mountaintop, gives way to dirt and grass. Nature forms an unbroken chain.`A single atom` attracts (and is attracted to) the next. Connections are everywhere. In a program, we combine things together (strings, ints). Tuples help us keep our logic clear and simple.`3 items.` Please note that the Tuple type is a class. Once we create the Tuple, we cannot change the values of its fields. This makes the Tuple more like a string. `Next: `In this example, we create a 3-item tuple using the special constructor syntax.`We then read the Item1, Item2 and Item3 properties and test them in if-statements. We do not modify them.`Item types.` When we create a Tuple, we specify the order and types of the fields. If you would rather have a double, byte, char Tuple, change the declaration to Tuple<double, byte, char>. `We can have value types (such as int) and reference types (such as string) inside a Tuple.`4 items.` Continuing on, a Tuple can have more complex items inside it, such as arrays. We can also pass the Tuple to other methods. `In this example, we create a four-item Tuple with two arrays—string and int arrays.`Arrays `array`Then: `We initialize those arrays inside the constructor invocation. Next we pass our Tuple variable to another method.`Var: `Why does the example use the var keyword? The reason is pure syntactic sugar. Var shortens the lines in the code example.`Var `var`6 items.` Tuples have different names. A sextuple has 6 items. To create a sextuple, use the Tuple constructor. You have to specify each type of the items in the type parameter list. `Warning: `This can lead to programs that have complex and hard-to-remember type names. But the compiler will check them.`Compile-Time Error `compile-time-error`In Visual Studio,` we can hover the mouse over the var keyword. This shows that the var "Represents a 6-tuple, or sextuple." Visual Studio further describes the tuple's individual types. `The naming of tuples is not important in many programs. But these terms can be useful when describing programs in a concise way.`Names: `Beyond septuples, we only have n-tuples. These terms will make you sound really smart.`Quote: `A tuple is an ordered list of elements. In mathematics, an n-tuple is a sequence (or ordered list) of "n" elements, where "n" is a non-negative integer.`Tuple: Wikipedia `https://en.wikipedia.org/wiki/Tuple`Tuple.Create.` Next we invoke this method. We use Create() with three arguments: a string literal, an integer and a boolean value. `Result: `The Create() method returns a class of type Tuple<string, int, bool>. It has three items.`Program: `The code does a series of tests of the Tuple. It tests Item1, Item2 and Item3.`Internals.` There is no elaborate algorithm devoted to tuple creation. The Tuple.Create method calls a constructor and returns a reference. `There is essentially no functional reason to ever call Tuple.Create. It might have more pleasing syntax.`Class implementation.` Tuple is not a struct. It is a class. It will be allocated upon the managed heap. Each class instance that is allocated adds to the burden of garbage collection. `The properties Item1, Item2 and further do not have setters. We cannot assign them. A Tuple is immutable once created in memory.`Property: Get, Set `property`Read-only.` We must initialize all values inside a Tuple to their final values when we call the constructor. We cannot change a property (like Item1) after the constructor has run. `This limitation can lead to more maintainable code that does not rely on field changes through time. It can also reduce performance.`Sort.` Tuples can be sorted. A Tuple is a great way to encapsulate units of data. But it can make sorting harder. A Comparison delegate is needed. `First: `This program creates a List and adds 3 new Tuple instances to it. We invoke the Sort method on the List.`Sort List `sort-list`We use the lambda syntax and pass in 2 arguments (a, b) and return the result of CompareTo on the Item2 string property.`To sort on the int, change the lambda to return a.Item1.CompareTo(b.Item1). A reverse sort would be b.Item2.CompareTo(a.Item2).`Return multiple values.` This is an age-old problem. A method may need to return many things, not just one. A tuple can return multiple values (with less code than a class would require). `This causes an allocation. Using ref and out parameters would be faster for a method that is hot.`Parameters `parameter`Note 2: `A Tuple has advantages. It is a reference and can be reused. Less copying is needed when passed to other methods.`ValueTuple.` This type has clear advantages over Tuple. We can specify a ValueTuple by including values in an expression (with no type names). `We create a 3-item tuple literal, and display its 3 items with Console.WriteLine.`ValueTuple `valuetuple`Console.WriteLine `console`Performance.` Here we benchmark Tuple, KeyValuePair and tuple literals (ValueTuple). This comparison is relevant only in cases for 2-item objects. `Important: `When a Tuple is passed as an argument, only a few bytes (4 or 8) need copying. But KeyValuePair (a struct) has more bytes.`Struct `struct`Look closely: `Please note there are 4 tests, and 3 objects are tested in each. We can determine the fastest object this way.`Notes, above benchmark.` We see 4 separate tests. The tests use different numbers of iterations to test the types. The average time in nanoseconds for each operation is computed. `Allocation: `In this test, one instance of a Tuple, KeyValuePair or tuple literal (ValueTuple) is allocated. The new-keyword is used.`Argument: `Here, one instance is passed as an argument to another (not inlined) method.`Return: `In this test, one instance is passed as an argument to a method and then returned.`Load: `In this method, one instance is loaded from a reference stored in a List collection.`Performance results.` The tuple literals (ValueTuple) are fastest when allocating. As arguments, the 3 types are all about the same speed. For returning from a method, Tuple is the fastest. `For accessing an item from the object, Tuple and tuple literals are the fastest (KeyValuePair is slower here).`Thanks to Alex Vincent for helping improve the complex benchmark of tuple objects.`A summary.` The Tuple is a typed, immutable, generic construct. That sounds impressive. Tuple is a useful container for storing conceptually-related data.`For important things,` a simple class with commented members and helper methods is more useful. But Tuple shines as a short-term container. `Class `class

?@B @P@O@S@D@; { ?@$?{B ??@{C@` three-item tuple. ??BTupleB<@}, @L, bool> tuple =@'@wTuple<@}, @L, bool>(B1B, B"cat"B, BtrueB);B ??@{Access tuple properties. ??B@rtuple.BItem1B@i1) ??{@'@%tuple.Item1); ??} ??@rtuple.BItem2B@iB"dog"B) ??{@'@%tuple.Item2); ??} ??@rtuple.BItem3B) ??{@'@%tuple.Item3); ??} ?} } B 1 TrueB @P@O@S@D@; { ?@$?{B ??@{C@` four-item tuple. ??@2Use var implicit type. ??BvarB tuple@z@wTuple<@L, @L[], @}, @}[]>(B"perl"B,@'@w@L[] { B"java"B, B"c#"B },@'1,@'@w@}[] { 2, 3 });B ??@{Pass tuple as argument. ??BM(tuple); ?} ?@A@fM(BTupleB<@L, @L[], @}, @}[]> tuple) ?{B ??@{Evaluate the tuple's items. ??B@%tuple.Item1); ??@7 (@L @d@ktuple.Item2) ??{@'@%@d); ??} ??@%tuple.Item3); ??@7 (@s@d@ktuple.Item4) ??{@'@%@d); ??} ?} } B perl java c# 1 2 3B @P@O@S@D@; { ?@$?{ ??BvarB sextuple =@'@wBTupleB<@}, @}, @}, @L, @L, @L>(1,@'1, 2, B"dot"B, B"net"B, B"perls"B); ??@%sextuple); ?} } B (1, 1, 2, dot, net, perls)BNames:B A 2-tuple is called a pair. A 3-tuple is called a triple. A 4-tuple is called a quadruple. A 5-tuple is called a qu@}uple. A 6-tuple is called a sextuple. A 7-tuple is called a septuple. Larger tuples are called n-tuples.B @P@O@S@D@; { ?@$?{B ??@{Use Tuple.C@` @Am@[. ??BvarB tuple@zBTuple.C@`B(B"cat"B, 2, true);B ??@{Test @d of @L. ??B@L @d@ztuple.Item1; ??@r@d@iB"cat"B) ??{@'@%true); ??}B ??@{Test Item2@RItem3. ??B@%tuple.Item2@i10); ??@%!tuple.Item3);B ??@{@h @L representation. ??B@%tuple); ?} } B True False False (cat, 2, True)BOne implementation of Tuple.C@`: .NET 4.0B @=@ATuple<T1> C@`<T1>(T1 item1) { ?@J @wTuple<T1>(item1); }BError:B Property or indexer '@O.Tuple...Item1' ?cannot be assigned to--it is read-only.B @P@O; @ @D@; { ?@$?{ ??@u<Tuple<@}, @L>> @t@z@w@u<Tuple<@}, @L>>(); ??@t.@n@wTuple<@}, @L>(B1B, B"cat"B)); ??@t.@n@wTuple<@}, @L>(B100B, B"apple"B)); ??@t.@n@wTuple<@}, @L>(B2B, B"zebra"B));B ??@{Use Sort m@[ with Comparison delegate. ??@2Has two parameters; @J comparison of Item2 on each. ??B@t.BSortB((a, b) => a.Item2.CompareTo(b.Item2))@S??@7 (var @6@k@t) ??{@'@%@6); ??} ?} } B (100, apple) (1, cat) (2, zebra)B @P@O@S@D@; { ?@ATuple<@L, @}> BNameAndIdB() ?{B ??@{This m@[ @Js multiple @ds. ??B@J @wTuple<@L, @}>(B"Satya Nadella"B, 100); ?} ?@$?{ ??var @I@zBNameAndIdB(); ??@L name@z@I.Item1; ??@sid@z@I.Item2;B ??@{@5 the multiple @ds @Jed. ??B@%name); ??@%id); ?} } B Satya Nadella 100B @P@O@S@D@; { ?@$?{B ??@{Go@lNuGet, then search @oand install @O.@eTuple. ??@2This program will then compile correctly. ??Bvar @ds@z(10, B"bird"B, B"plane"B); ??@%@ds); ??@%@ds.BItem1B); ??@%@ds.BItem2B); ??@%@ds.BItem3B); ?} } B (10, bird, plane) 10 bird planeB @P@O; @ @!@P@O.Runtime.CompilerServices@S@D@; { ?@$?{ ??Allocation(); ??Argument(); ??Return(); ??Load(); ?} ?@A@fBAllocationB() ?{B ??@{Time allocating the object. ??Bconst @smax@z1000000; ??var a@z@wTuple<@L, @L>(B""B, B""B); ??var b@z@wKey@ePair<@L, @L>(B""B, B""B); ??var c@z("", "")@S??var s1@z@-.@cNew(); ??@o(var i@z0; i < max; i++) ??{@'var tuple@z@wTuple<@L, @L>(B"cat"B, B"dog"B); ??} ??s1@1; ??var s2@z@-.@cNew(); ??@o(var i@z0; i < max; i++) ??{@'var pair@z@wKey@ePair<@L, @L>(B"cat"B, B"dog"B); ??} ??s2@1; ??var s3@z@-.@cNew(); ??@o(var i@z0; i < max; i++) ??{@'var pair@z(B"cat"B, B"dog"B); ??} ??s3@1; ??@%(@.(s1.@" * 1000000) / max)@yB" allocation, Tuple"B); ??@%(@.(s2.@" * 1000000) / max)@yB" allocation, Key@ePair"B); ??@%(@.(s3.@" * 1000000) / max)@yB" allocation, Tuple literal"B); ??@%); ?} ?@A@fBArgumentB() ?{B ??@{Time passing the object as an argument@la function. ??Bconst @smax@z10000000; ??var a@z@wTuple<@L, @L>(B""B, B""B); ??var b@z@wKey@ePair<@L, @L>(B""B, B""B); ??var c@z(B""B, B""B); ??X(a); ??X(b); ??X(c)@S??var s1@z@-.@cNew(); ??@o(var i@z0; i < max; i++) ??{@'X(a); ??} ??s1@1; ??var s2@z@-.@cNew(); ??@o(var i@z0; i < max; i++) ??{@'X(b); ??} ??s2@1; ??var s3@z@-.@cNew(); ??@o(var i@z0; i < max; i++) ??{@'X(c); ??} ??s3@1; ??@%(@.(s1.@" * 1000000) / max)@yB" argument, Tuple"B); ??@%(@.(s2.@" * 1000000) / max)@yB" argument, Key@ePair"B); ??@%(@.(s3.@" * 1000000) / max)@yB" argument, Tuple literal"B); ??@%); ?} ?@A@fBReturnB() ?{B ??@{Time @Jing the object itself. ??Bconst @smax@z10000000; ??var a@z@wTuple<@L, @L>(B""B, B""B); ??var b@z@wKey@ePair<@L, @L>(B""B, B""B); ??var c@z(B""B, B""B); ??Y(a); ??Y(b); ??Y(c)@S??var s1@z@-.@cNew(); ??@o(var i@z0; i < max; i++) ??{@'Y(a); ??} ??s1@1; ??var s2@z@-.@cNew(); ??@o(var i@z0; i < max; i++) ??{@'Y(b); ??} ??s2@1; ??var s3@z@-.@cNew(); ??@o(var i@z0; i < max; i++) ??{@'Y(c); ??} ??s3@1; ??@%(@.(s1.@" * 1000000) / max)@yB" @J, Tuple"B); ??@%(@.(s2.@" * 1000000) / max)@yB" @J, Key@ePair"B); ??@%(@.(s3.@" * 1000000) / max)@yB" @J, Tuple literal"B); ??@%); ?} ?@A@fBLoadB() ?{B ??@{Time accessing an @6. ??Bconst @smax@z10000000; ??var a@z@wTuple<@L, @L>(B"cat"B, B"dog"B); ??var b@z@wKey@ePair<@L, @L>(B"cat"B, B"dog"B); ??var c@z(B"cat"B, B"dog"B)@S??var @t1@z@w@u<Tuple<@L, @L>>(); ??@t1.@na); ??Z(@t1)@S??var @t2@z@w@u<Key@ePair<@L, @L>>(); ??@t2.@nb); ??Z(@t2)@S??var @t3@z@w@u<(@L, @L)>(); ??@t3.@nc); ??Z(@t3)@S??var s1@z@-.@cNew(); ??@o(var i@z0; i < max; i++) ??{@'Z(@t1); ??} ??s1@1; ??var s2@z@-.@cNew(); ??@o(var i@z0; i < max; i++) ??{@'Z(@t2); ??} ??s2@1; ??var s3@z@-.@cNew(); ??@o(var i@z0; i < max; i++) ??{@'Z(@t3); ??} ??s3@1; ??@%(@.(s1.@" * 1000000) / max)@yB" load, Tuple"B); ??@%(@.(s2.@" * 1000000) / max)@yB" load, Key@ePair"B); ??@%(@.(s3.@" * 1000000) / max)@yB" load, Tuple literal"B); ??@%); ?} ?[M@[Impl(M@[ImplOptions.NoInlining)] ?@A@fX(Tuple<@L, @L> a) ?{B ??@{This@Rfollowing m@[s are used@kthe benchmarks. ?B} ?[M@[Impl(M@[ImplOptions.NoInlining)] ?@A@fX(Key@ePair<@L, @L> a) ?{ ?} ?[M@[Impl(M@[ImplOptions.NoInlining)] ?@A@fX((@L, @L) a) ?{ ?} ?[M@[Impl(M@[ImplOptions.NoInlining)] ?@ATuple<@L, @L> Y(Tuple<@L, @L> a) ?{ ??@J a; ?} ?[M@[Impl(M@[ImplOptions.NoInlining)] ?@AKey@ePair<@L, @L> Y(Key@ePair<@L, @L> a) ?{ ??@J a; ?} ?[M@[Impl(M@[ImplOptions.NoInlining)] ?@A(@L, @L) Y((@L, @L) a) ?{ ??@J a; ?} ?@Achar Z(@u<Tuple<@L, @L>> @t) ?{ ??@J @t[0].Item1[0]; ?} ?@Achar Z(@u<Key@ePair<@L, @L>> @t) ?{ ??@J @t[0].Key[0]; ?} ?@Achar Z(@u<(@L, @L)> @t) ?{ ??@J @t[0].Item1[0]; ?} } BResultsB B8.3944B allocation, Tuple B0.4949B allocation, Key@ePair B0.3457B allocation, Tuple literal (FASTEST) B2.16168B argument, Tuple B2.17551B argument, Key@ePair B2.17316B argument, Tuple literal B1.84421B @J, Tuple (FASTEST) B5.42422B @J, Key@ePair B5.32932B @J, Tuple literal B2.44545B load, Tuple B3.27982B load, Key@ePair B2.56207B load, Tuple literalB

`3 items in Tuple\4-item Tuple\6-item tuplecTuple.Create method=sorts List of Tuple instances7returns multiple values^tuple literals6benchmarks tuple types