<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="http://blogs.msdn.com/utility/FeedStylesheets/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/"><channel><title>jaredpar's WebLog : Tuple</title><link>http://blogs.msdn.com/jaredpar/archive/tags/Tuple/default.aspx</link><description>Tags: Tuple</description><dc:language>en-US</dc:language><generator>CommunityServer 2.1 SP1 (Build: 61025.2)</generator><item><title>Tuples Part 8: Finishing up</title><link>http://blogs.msdn.com/jaredpar/archive/2008/01/27/tuples-part-8-finishing-up.aspx</link><pubDate>Mon, 28 Jan 2008 05:37:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7278167</guid><dc:creator>Jared Parsons</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/jaredpar/comments/7278167.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jaredpar/commentrss.aspx?PostID=7278167</wfw:commentRss><wfw:comment>http://blogs.msdn.com/jaredpar/rsscomments.aspx?PostID=7278167</wfw:comment><description>&lt;p&gt;There are only a few missing features from our tuple implementation.&amp;#160; Mainly FxCop compliance, debugging support and test case code.&amp;#160; The actual functional work is complete.&amp;#160; &lt;/p&gt;  &lt;p&gt;The one issue with FxCop compliance is the chosen names.&amp;#160; Namely using A,B etc.&amp;#160; FxCop, rightly, believes names should have more value.&amp;#160; Accordingly, calling the generic argument corresponding to A, TA also causes the same issue.&amp;#160; This is a design decision made from the &lt;a href="http://blogs.msdn.com/jaredpar/archive/2008/01/03/tuples-part-1.aspx"&gt;begining&lt;/a&gt;.&amp;#160; I don't believe changing the name to ValueA adds any more value than simply A.&amp;#160; Therefore the warning for this will simply be suppressed. &lt;/p&gt;  &lt;p&gt;Additionally FxCop doesn't like types with more than 3 generic parameters.&amp;#160; This is also a design decision intentionally done and there is no avoiding it.&amp;#160; It will be suppressed as well.&amp;#160; &lt;/p&gt;  &lt;p&gt;For debugging support a simple &lt;a href="http://msdn2.microsoft.com/en-us/library/x810d419.aspx"&gt;DebuggerDisplay attribute&lt;/a&gt; will be used.&amp;#160; It will display the current value of all of the tuple values.&amp;#160; &lt;/p&gt;  &lt;p&gt;Here is the latest version of the full script which includes all of the new information.&amp;#160; With the exception of a few small tweaks this is just the combination of the individual parts specified throughout these postings.&lt;/p&gt;  &lt;p&gt;param ( [int]$tupleCount = 5,   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; [string]$namespace = &amp;quot;Tuples&amp;quot; ) &lt;/p&gt;  &lt;p&gt;$script:scriptPath = split-path -parent $MyInvocation.MyCommand.Definition    &lt;br /&gt;$script:lowerList = 0..25 | %{ [char]([int][char]'a'+$_) }    &lt;br /&gt;$script:upperList = 0..25 | %{ [char]([int][char]'A'+$_) }    &lt;br /&gt;$script:valueList = &amp;quot;1&amp;quot;,&amp;quot;42&amp;quot;,'&amp;quot;bar&amp;quot;', '&amp;quot;foo&amp;quot;', 'true' &lt;/p&gt;  &lt;p&gt;function script:Gen-FxCop   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int]$code ) &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; switch ( $code )   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1704 { '[SuppressMessage(&amp;quot;Microsoft.Naming&amp;quot;, &amp;quot;CA1704&amp;quot;)]'; break }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 1005 { '[SuppressMessage(&amp;quot;Microsoft.Design&amp;quot;, &amp;quot;CA1005&amp;quot;)]'; break }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; default: {$(throw &amp;quot;Invalid&amp;quot;)}    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function script:Gen-Display   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int]$count )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = &amp;quot;, &amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $p = [string](0..($count-1) | %{ &amp;quot;{0}={{{0}}}&amp;quot; -f $upperList[$_] })    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; '[DebuggerDisplay(&amp;quot;{0}&amp;quot;)]' -f $p    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function script:Gen-Property   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $index&amp;#160; = $(throw &amp;quot;Need an index&amp;quot;), [bool]$mutable = $false) &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; if (-not $mutable )   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;@&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private readonly T{0} m_{1};    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $(Gen-FxCop 1704)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public T{0} {0} {{ get {{ return m_{1}; }} }} &lt;/p&gt;  &lt;p&gt;&amp;quot;@ -f $upperList[$index],$lowerList[$index]   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; else    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;@&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private T{0} m_{1};    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $(Gen-FxCop 1704)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public T{0} {0} {{ get {{ return m_{1}; }} set {{ m_{1} = value; }} }} &lt;/p&gt;  &lt;p&gt;&amp;quot;@ -f $upperList[$index],$lowerList[$index]   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function script:Gen-Constructor   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count = $(throw &amp;quot;Need a count&amp;quot;), [string]$className )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = ','    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $list = [string](0..$($count-1) | %{ &amp;quot;T{0} value{0}&amp;quot; -f $upperList[$_]})    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public $className($list) {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 0..($count-1) | %{ &amp;quot;m_{0} = value{1};&amp;quot; -f $lowerList[$_],$upperList[$_] }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot;    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function script:Gen-InferenceConstructor   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count = $(throw &amp;quot;Need a count&amp;quot;), [string]$name )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = ','    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $gen = &amp;quot;&amp;lt;&amp;quot; + [string](0..($count-1) | %{ &amp;quot;T&amp;quot;+$upperList[$_] }) + &amp;quot;&amp;gt;&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $list = [string](0..$($count-1) | %{ &amp;quot;T{0} value{0}&amp;quot; -f $upperList[$_] })    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $argList = [string](0..$($count-1) | %{ &amp;quot;value{0}&amp;quot; -f $upperList[$_] })    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public static partial class $name {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Gen-FxCop 1704    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public static $name$gen Create$gen($list) { return new $name$gen($argList); } &amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot;    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function script:Gen-Equals   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count = $(throw &amp;quot;Need a count&amp;quot;), [string]$name )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = ','    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $gen = &amp;quot;&amp;lt;&amp;quot; + [string](0..($count-1) | %{ &amp;quot;T&amp;quot;+$upperList[$_] }) + &amp;quot;&amp;gt;&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public override bool Equals(object obj) { &amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return Equals(obj as $name$gen); }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public bool Equals($name$gen other) {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;if ( Object.ReferenceEquals(other,null) ) { return false; }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;if (&amp;quot;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = &amp;quot;&amp;amp;&amp;amp;&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [string](0..($count-1) | %{&amp;quot;EqualityComparer&amp;lt;T{0}&amp;gt;.Default.Equals(m_{1},other.m_{1})&amp;quot; -f $upperList[$_],$lowerList[$_] })    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;) { return true; }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return false;&amp;quot;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot;    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function script:Gen-GetHashCode   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count = $(throw &amp;quot;Need a count&amp;quot;) )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public override int GetHashCode() {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;int code = 0;&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 0..($count-1) | %{ &amp;quot;code += EqualityComparer&amp;lt;T{0}&amp;gt;.Default.GetHashCode(m_{1});&amp;quot; -f $upperList[$_],$lowerList[$_] }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return code;&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot;    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function script:Gen-ITuple   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count = $(throw &amp;quot;Need a count&amp;quot;) )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = ','    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $gen = &amp;quot;&amp;lt;&amp;quot; + [string](0..($count-1) | %{ &amp;quot;T&amp;quot;+$upperList[$_] }) + &amp;quot;&amp;gt;&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $base = &amp;quot;&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if ( $count -ne 1 )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $baseGen = &amp;quot;&amp;lt;&amp;quot; + [string](0..($count-2) | %{ &amp;quot;T&amp;quot;+$upperList[$_] }) + &amp;quot;&amp;gt;&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $base = &amp;quot;: ITuple$baseGen&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; else    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $base = &amp;quot;: ITuple&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Gen-FxCop 1704    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if ( $count -gt 2 ) { Gen-FxCop 1005 }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public interface ITuple$gen $base {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Gen-FxCop 1704    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;T{0} {0} {{ get; }}&amp;quot; -f $upperList[$count-1]&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot;    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function script:Gen-TupleAccess   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count = $(throw &amp;quot;Need a count&amp;quot;), [bool]$mutable )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public int Count { get { return $count; } }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public object this[int index] { get { switch (index){ &amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 0..($count-1) | %{ &amp;quot;case $($_): return m_$($lowerList[$_]);&amp;quot; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;default: throw new InvalidOperationException(&amp;quot;&amp;quot;Bad Index&amp;quot;&amp;quot;);&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;} }&amp;quot; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; if ( $mutable )   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;set { switch (index) {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0..($count-1) | %{ &amp;quot;case $($_): m_$($lowerList[$_]) = (T$($upperList[$_]))value; break;&amp;quot; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;default: throw new InvalidOperationException(&amp;quot;&amp;quot;Bad Index&amp;quot;&amp;quot;);&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;} } &amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot;    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function script:Gen-OpEquals   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count = $(throw &amp;quot;Need a count&amp;quot;), [string]$name )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = ','    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $gen = &amp;quot;&amp;lt;&amp;quot; + [string](0..($count-1) | %{ &amp;quot;T&amp;quot;+$upperList[$_] }) + &amp;quot;&amp;gt;&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public static bool operator==($name$gen left, $name$gen right) {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return EqualityComparer&amp;lt;$name$gen&amp;gt;.Default.Equals(left,right); }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public static bool operator!=($name$gen left, $name$gen right) {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return !EqualityComparer&amp;lt;$name$gen&amp;gt;.Default.Equals(left,right); }&amp;quot;    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function script:Gen-CompareTo   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count = $(throw &amp;quot;Need a count&amp;quot;), [string]$name )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = ','    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $gen = &amp;quot;&amp;lt;&amp;quot; + [string](0..($count-1) | %{ &amp;quot;T&amp;quot;+$upperList[$_] }) + &amp;quot;&amp;gt;&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public int CompareTo(object obj) {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return CompareTo(obj as $name$gen); }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public int CompareTo($name$gen other) {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;if ( Object.ReferenceEquals(other,null) ) { return 1; }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;int code;&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 0..($count-1) |     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; %{ &amp;quot;code = Comparer&amp;lt;T{0}&amp;gt;.Default.Compare(m_{1},other.m_{1}); if (code != 0) {{ return code; }}&amp;quot; -f $upperList[$_],$lowerList[$_] }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return 0; }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public static bool operator&amp;gt;($name$gen left, $name$gen right) { &amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return Comparer&amp;lt;$name$gen&amp;gt;.Default.Compare(left,right) &amp;gt; 0; }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public static bool operator&amp;lt;($name$gen left, $name$gen right) { &amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return Comparer&amp;lt;$name$gen&amp;gt;.Default.Compare(left,right) &amp;lt; 0; }&amp;quot;    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function script:Get-Tuple   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count, [bool]$mutable = $false )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = ','    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $gen = &amp;quot;&amp;lt;&amp;quot; + [string](0..($count-1) | %{ &amp;quot;T&amp;quot;+$upperList[$_] }) + &amp;quot;&amp;gt;&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Gen-FxCop 1704    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Gen-Display $count    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; if ( $count -gt 2 ) { Gen-FxCop 1005 }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $name = &amp;quot;{0}Tuple&amp;quot; -f (Get-Ternary $mutable &amp;quot;Mutable&amp;quot; &amp;quot;&amp;quot;)    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public sealed class $name$gen : ITuple$gen,IEquatable&amp;lt;$name$gen&amp;gt;, IComparable&amp;lt;$name$gen&amp;gt;,IComparable {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; (0..($count-1) | %{ Gen-Property $_ $mutable})    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Gen-Constructor $count $name    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Gen-TupleAccess $count $mutable    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Gen-Equals $count $name    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Gen-GetHashCode $count    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Gen-OpEquals $count $name    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Gen-CompareTo $count $name    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; Gen-InferenceConstructor $count $name    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;function Gen-TestTuple([int]$count, [string]$prefix)   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = &amp;quot;,&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $v = [string](0..($count-1) | %{ $valueList[$_]} )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;[TestMethod]&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public void {0}Access{1}() {{&amp;quot; -f $prefix,$count    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;var t = $prefix.Create($v);&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; for ( $i = 0; $i -lt $count; ++$i )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Assert.AreEqual({0},t.{1});&amp;quot; -f $valueList[$i],$upperList[$i];    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;[TestMethod]&amp;quot;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public void {0}GenericAccess{1}() {{&amp;quot; -f $prefix,$count    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;var t = $prefix.Create($v);&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; for ( $i = 0; $i -lt $count; ++$i )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; (&amp;quot;Assert.AreEqual({0},t[{1}]);&amp;quot; -f $valueList[$i],$i);    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Assert.AreEqual({0},t.Count);&amp;quot; -f $i     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;[TestMethod]&amp;quot;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public void {0}Equals{1}() {{&amp;quot; -f $prefix,$count    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;var t1 = $prefix.Create($v);&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;var t2 = $prefix.Create($v);&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Assert.IsTrue(t1.Equals(t2));&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;[TestMethod]&amp;quot;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public void {0}NotEquals{1}() {{&amp;quot; -f $prefix,$count    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; for ( $i = 0; $i -lt $count; ++$i )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $leftName = &amp;quot;t{0}_1&amp;quot; -f $i    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $rightName = &amp;quot;t{0}_2&amp;quot; -f $i    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $left = &amp;quot;var $leftName = $prefix.Create(&amp;quot; -f $i    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $right = &amp;quot;var $rightName = $prefix.Create(&amp;quot; -f $i    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; for ( $v = 0; $v -lt $count; ++$v )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $left += &amp;quot;$v&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ( $v -eq $i )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $right += &amp;quot;-1&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; else    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $right += &amp;quot;$v&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; } &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; if ( ($v + 1) -lt $count )   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $left += &amp;quot;,&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; $right += &amp;quot;,&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;$left);&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;$right);&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Assert.AreEqual($leftName.GetType(), $rightName.GetType());&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Assert.IsFalse($leftName.Equals($rightName));&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot; &lt;/p&gt;  &lt;p&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;[TestMethod]&amp;quot;   &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public void {0}CompareTest() {{ &amp;quot; -f $prefix    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Assert.IsTrue($prefix.Create(1) &amp;lt; $prefix.Create(2));&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;Assert.IsTrue($prefix.Create(2) &amp;gt; $prefix.Create(1));&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot;    &lt;br /&gt;} &lt;/p&gt;  &lt;p&gt;$output =    &lt;br /&gt;@&amp;quot;    &lt;br /&gt;using System;    &lt;br /&gt;using System.Collections.Generic;    &lt;br /&gt;using System.Diagnostics;    &lt;br /&gt;using System.Diagnostics.CodeAnalysis; &lt;/p&gt;  &lt;p&gt;namespace $namespace {    &lt;br /&gt;public interface ITuple {    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; int Count { get; }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; object this[int index] { get; }    &lt;br /&gt;}    &lt;br /&gt;&amp;quot;@    &lt;br /&gt;$OFS = [Environment]::NewLine    &lt;br /&gt;$output += [string](0..($tupleCount-1) | %{ Gen-ITuple ($_+1) })    &lt;br /&gt;$output += [string](0..($tupleCount-1) | %{ Get-Tuple ($_+1) })    &lt;br /&gt;$output += [string](0..($tupleCount-1) | %{ Get-Tuple ($_+1) $true })    &lt;br /&gt;$output += &amp;quot;}&amp;quot; &lt;/p&gt;  &lt;p&gt;$output &amp;gt; (join-path $scriptPath &amp;quot;Core\Tuple.cs&amp;quot;) &lt;/p&gt;  &lt;p&gt;$output =    &lt;br /&gt;@&amp;quot;    &lt;br /&gt;using System;    &lt;br /&gt;using System.Collections.Generic;    &lt;br /&gt;using Microsoft.VisualStudio.TestTools.UnitTesting;    &lt;br /&gt;using $namespace; &lt;/p&gt;  &lt;p&gt;namespace $($nameSpace)Test { &lt;/p&gt;  &lt;p&gt;[TestClass]   &lt;br /&gt;public class TupleTest{    &lt;br /&gt;&amp;quot;@    &lt;br /&gt;$output += Gen-TestTuple $tupleCount &amp;quot;Tuple&amp;quot;    &lt;br /&gt;$output += Gen-TestTuple $tupleCount &amp;quot;MutableTuple&amp;quot;    &lt;br /&gt;$output += &amp;quot;}}&amp;quot;    &lt;br /&gt;$output &amp;gt; (join-path $scriptPath &amp;quot;TestCore\TupleTest.cs&amp;quot;) &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7278167" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jaredpar/archive/tags/PowerShell/default.aspx">PowerShell</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/FxCop/default.aspx">FxCop</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Generics/default.aspx">Generics</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Tuple/default.aspx">Tuple</category></item><item><title>Tuples Part 7: Mutable Tuples</title><link>http://blogs.msdn.com/jaredpar/archive/2008/01/23/tuples-part-7-mutable-tuples.aspx</link><pubDate>Wed, 23 Jan 2008 10:56:19 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7206269</guid><dc:creator>Jared Parsons</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/jaredpar/comments/7206269.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jaredpar/commentrss.aspx?PostID=7206269</wfw:commentRss><wfw:comment>http://blogs.msdn.com/jaredpar/rsscomments.aspx?PostID=7206269</wfw:comment><description>&lt;p&gt;&lt;a href="http://blogs.msdn.com/jaredpar/archive/2008/01/22/tuples-part-6-comparing.aspx"&gt;Part 6&lt;/a&gt; left us with comparable tuples.&amp;#160; At this point, the Tuple class is functionally complete.&amp;#160; There will be a little more done with the debugability and overall fit into larger projects.&amp;#160; But otherwise it is sound.&amp;#160; &lt;/p&gt;  &lt;p&gt;Now the focus shifts to generating mutable tuples.&amp;#160; Immutability is nice for threading, memoization, etc ...&amp;#160; However it's not always practical to use immutable objects.&amp;#160; Often an algorithm does not benefit from immutability and lends itself to a more mutable type.&amp;#160; &lt;/p&gt;  &lt;p&gt;Mutable tuples behave like a Tuple in every other way except that they're ... mutable.&amp;#160; This includes implementing interfaces as well as inheritance structure.&amp;#160; &lt;/p&gt;  &lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;sealed&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;MutableTuple&lt;/span&gt;&amp;lt;TA, TB&amp;gt; : 
    &lt;span style="color: rgb(43,145,175)"&gt;ITuple&lt;/span&gt;&amp;lt;TA, TB&amp;gt;, 
    &lt;span style="color: rgb(43,145,175)"&gt;IEquatable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43,145,175)"&gt;MutableTuple&lt;/span&gt;&amp;lt;TA, TB&amp;gt;&amp;gt;, 
    &lt;span style="color: rgb(43,145,175)"&gt;IComparable&lt;/span&gt;&amp;lt;&lt;span style="color: rgb(43,145,175)"&gt;MutableTuple&lt;/span&gt;&amp;lt;TA, TB&amp;gt;&amp;gt;, 
    &lt;span style="color: rgb(43,145,175)"&gt;IComparable
&lt;/span&gt;{&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;

&lt;p&gt;As such the script already used will be sufficient to generate mutable classes in addition to the ones its already doing.&amp;#160; The majority of the code difference is just in the naming of the classes.&amp;#160; The only functional differences exist in the properties and indexer.&amp;#160; Both of these add a setter method.&amp;#160; Below is the modified code for generating the property and indexer.&amp;#160; &lt;/p&gt;

&lt;p&gt;function script:Gen-TupleAccess
  &lt;br /&gt;{

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count = $(throw &amp;quot;Need a count&amp;quot;), [bool]$mutable )

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public int Count { get { return $count; } }&amp;quot;

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public object this[int index] { get { switch (index){ &amp;quot;

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 0..($count-1) | %{ &amp;quot;case $($_): return m_$($lowerList[$_]);&amp;quot; }

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;default: throw new InvalidOperationException(&amp;quot;&amp;quot;Bad Index&amp;quot;&amp;quot;);&amp;quot;

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;} }&amp;quot; &lt;/p&gt;

&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; if ( $mutable )
  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;set { switch (index) {&amp;quot;

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; 0..($count-1) | %{ &amp;quot;case $($_): m_$($lowerList[$_]) = (T$($upperList[$_]))value; break;&amp;quot; }

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;default: throw new InvalidOperationException(&amp;quot;&amp;quot;Bad Index&amp;quot;&amp;quot;);&amp;quot;

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &amp;quot;} } &amp;quot;

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot;

  &lt;br /&gt;}&lt;/p&gt;

&lt;p&gt;function script:Gen-Property
  &lt;br /&gt;{

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $index&amp;#160; = $(throw &amp;quot;Need an index&amp;quot;), [bool]$mutable = $false) &lt;/p&gt;

&lt;p&gt;&amp;#160;&amp;#160;&amp;#160; if (-not $mutable )
  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {

  &lt;br /&gt;@&amp;quot;

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private readonly T{0} m_{1};

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public T{0} {0} {{ get {{ return m_{1}; }} }} &lt;/p&gt;

&lt;p&gt;&amp;quot;@ -f $upperList[$index],$lowerList[$index]
  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; else

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; {

  &lt;br /&gt;@&amp;quot;

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; private T{0} m_{1};

  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; public T{0} {0} {{ get {{ return m_{1}; }} set {{ m_{1} = value; }} }} &lt;/p&gt;

&lt;p&gt;&amp;quot;@ -f $upperList[$index],$lowerList[$index]
  &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; }

  &lt;br /&gt;}&lt;/p&gt;

&lt;p&gt;Now creating a mutable tuple is the same as the immutable tuple with just a name tweak.&lt;/p&gt;

&lt;pre class="code"&gt;            &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; t1 = &lt;span style="color: rgb(43,145,175)"&gt;MutableTuple&lt;/span&gt;.Create(&lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;foo&amp;quot;&lt;/span&gt;, 42);
            t1.A = &lt;span style="color: rgb(163,21,21)"&gt;&amp;quot;again&amp;quot;&lt;/span&gt;;&lt;/pre&gt;
&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7206269" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jaredpar/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Threading/default.aspx">Threading</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Immutable/default.aspx">Immutable</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Tuple/default.aspx">Tuple</category></item><item><title>Tuples Part 6: Comparing</title><link>http://blogs.msdn.com/jaredpar/archive/2008/01/22/tuples-part-6-comparing.aspx</link><pubDate>Tue, 22 Jan 2008 09:56:00 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7194139</guid><dc:creator>Jared Parsons</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/jaredpar/comments/7194139.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jaredpar/commentrss.aspx?PostID=7194139</wfw:commentRss><wfw:comment>http://blogs.msdn.com/jaredpar/rsscomments.aspx?PostID=7194139</wfw:comment><description>&lt;P&gt;&lt;A href="http://blogs.msdn.com/jaredpar/archive/2008/01/22/tuples-part-5-equality.aspx" mce_href="http://blogs.msdn.com/jaredpar/archive/2008/01/22/tuples-part-5-equality.aspx"&gt;Part 5&lt;/A&gt; produced equality tests for Tuples.&amp;nbsp; This section will add comparison support through the &lt;A href="http://msdn2.microsoft.com/en-us/library/4d7sx9hd.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/4d7sx9hd.aspx"&gt;IComparable&amp;lt;T&amp;gt;&lt;/A&gt; interface.&amp;nbsp; Implementing comparable is very similar to adding equality support.&amp;nbsp; Once again there is a generic class available to make all of the comparison decisions for us; &lt;A href="http://msdn2.microsoft.com/en-us/library/cfttsh47.aspx" mce_href="http://msdn2.microsoft.com/en-us/library/cfttsh47.aspx"&gt;Comparer&amp;lt;T&amp;gt;&lt;/A&gt;.&amp;nbsp; &lt;/P&gt;
&lt;P&gt;The implementation will compare objects in a left to right fashion.&amp;nbsp; In this case the property corresponding to TA will be the left most, and TN the right most.&amp;nbsp; If all properties are equal (Compare returns 0) then the two items will be determined to be equal and will return 0.&lt;/P&gt;
&lt;P&gt;function script:Gen-CompareTo &lt;BR&gt;{ &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; param ( [int] $count = $(throw "Need a count") ) &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $OFS = ',' &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $gen = "&amp;lt;" + [string](0..($count-1) | %{ "T"+$upperList[$_] }) + "&amp;gt;"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "public int CompareTo(object other) {" &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "return CompareTo(other as Tuple$gen); }" &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "public int CompareTo(Tuple$gen other) {" &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "if ( Object.ReferenceEquals(other,null) ) { return 1; }" &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "int code;" &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0..($count-1) | &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; %{ "code = Comparer&amp;lt;T{0}&amp;gt;.Default.Compare(m_{1},other.m_{1}); if (code != 0) {{ return code; }}" -f $upperList[$_],$lowerList[$_] } &lt;BR&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "return 0; }" &lt;BR&gt;}&lt;/P&gt;
&lt;P&gt;Once again the same questions arise about implementing IComparable&amp;lt;Tuple&amp;gt; vs IComparable&amp;lt;ITuple&amp;gt; (or both).&amp;nbsp; The arguments are fairly similar and as a result I decided to skip implementing the ITuple version for now.&lt;/P&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7194139" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jaredpar/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Generics/default.aspx">Generics</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Patterns/default.aspx">Patterns</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Tuple/default.aspx">Tuple</category></item><item><title>Tuples Part 5: Equality</title><link>http://blogs.msdn.com/jaredpar/archive/2008/01/22/tuples-part-5-equality.aspx</link><pubDate>Tue, 22 Jan 2008 09:31:18 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7193911</guid><dc:creator>Jared Parsons</dc:creator><slash:comments>2</slash:comments><comments>http://blogs.msdn.com/jaredpar/comments/7193911.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jaredpar/commentrss.aspx?PostID=7193911</wfw:commentRss><wfw:comment>http://blogs.msdn.com/jaredpar/rsscomments.aspx?PostID=7193911</wfw:comment><description>&lt;p&gt;&lt;a href="http://blogs.msdn.com/jaredpar/archive/2008/01/10/tuples-part-4-interface.aspx"&gt;Part 4&lt;/a&gt; left us with a reusable, abstract and inference friendly Tuple class.&amp;#160; The next step is to be able to test for Tuple equality.&amp;#160; &lt;/p&gt;  &lt;p&gt;For the Tuple implementation, two tuples will be defined as equal if all of their members are equal.&amp;#160; Seems fairly straight forward.&amp;#160; The trick is in the implementation.&amp;#160; In addition to doing the typical override of Equals/GetHashCode the Tuple implementation will be implementing &lt;a href="http://msdn2.microsoft.com/en-us/library/ms131187.aspx"&gt;IEquatable&amp;lt;T&amp;gt;&lt;/a&gt; and overloading the standard equality operators.&lt;/p&gt;  &lt;p&gt;Tuple members are all unconstrained generic classes which leaves us with a non-great starting point.&amp;#160; &lt;/p&gt;  &lt;p&gt;For instance what if we are dealing with value types?&amp;#160; Is Equals() the best method to call?&amp;#160; What if the type in question implements &lt;a href="http://msdn2.microsoft.com/en-us/library/ms131187.aspx"&gt;IEquatable&amp;lt;T&amp;gt;&lt;/a&gt; or has a well known &lt;a href="http://msdn2.microsoft.com/en-us/library/ms132151.aspx"&gt;IEqualityComparer&amp;lt;T&amp;gt;&lt;/a&gt;?&amp;#160;&amp;#160; What if one or both of the arguments are reference types and null? What if they're value types and equal to null?&lt;/p&gt;  &lt;p&gt;Luckily there is an easy and straight forward solution.&amp;#160; The BCL defines a class, &lt;a href="http://msdn2.microsoft.com/en-us/library/ms132123.aspx"&gt;EqualityComparer&amp;lt;T&amp;gt;&lt;/a&gt;, which will properly perform equality comparisons for objects of a particular type.&amp;#160; This makes the Equals override very straight forward. &lt;/p&gt;  &lt;p&gt;There is one small trick to implementing Equals correctly.&amp;#160; The implementation explicitly uses Object.ReferenceEquals to check for null rather than ==.&amp;#160; The reason being is once operator== is defined for the type Tuple, comparison for even null will bind to this operator.&amp;#160; Part of checking for operator== will end up calling Equals and hence you can end in a stack overflow fairly quick.&amp;#160; Note that our implementation of == will work around this but it's still safer to be explicit.&amp;#160; &lt;/p&gt;  &lt;p&gt;function script:Gen-Equals   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count = $(throw &amp;quot;Need a count&amp;quot;) )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = ','    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $gen = &amp;quot;&amp;lt;&amp;quot; + [string](0..($count-1) | %{ &amp;quot;T&amp;quot;+$upperList[$_] }) + &amp;quot;&amp;gt;&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public override bool Equals(object obj) { &amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return Equals(obj as Tuple$gen); }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public bool Equals(Tuple$gen other) {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;if ( Object.ReferenceEquals(other,null) ) { return false; }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;if (&amp;quot;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = &amp;quot;&amp;amp;&amp;amp;&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; [string](0..($count-1) | %{&amp;quot;EqualityComparer&amp;lt;T{0}&amp;gt;.Default.Equals(m_{1},other.m_{1})&amp;quot; -f $upperList[$_],$lowerList[$_] })    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;) { return true; }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return false;&amp;quot;     &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot;    &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;GetHashCode can also utilize &lt;a href="http://msdn2.microsoft.com/en-us/library/ms132123.aspx"&gt;EqualityComparer&amp;lt;T&amp;gt;&lt;/a&gt;.&lt;/p&gt;  &lt;p&gt;function script:Gen-GetHashCode   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count = $(throw &amp;quot;Need a count&amp;quot;) )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public override int GetHashCode() {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;int code = 0;&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; 0..($count-1) | %{ &amp;quot;code += EqualityComparer&amp;lt;T{0}&amp;gt;.Default.GetHashCode(m_{1});&amp;quot; -f $upperList[$_],$lowerList[$_] }    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return code;&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;}&amp;quot;    &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;Both of the operators are likewise straight forward.&amp;#160; As before mentioned &lt;a href="http://msdn2.microsoft.com/en-us/library/ms132123.aspx"&gt;EqualityComparer&amp;lt;T&amp;gt;&lt;/a&gt; will properly check for null and then perform an Equals call so it can be used as the standard operator code.&amp;#160; &lt;/p&gt;  &lt;p&gt;function script:Gen-OpEquals   &lt;br /&gt;{    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; param ( [int] $count = $(throw &amp;quot;Need a count&amp;quot;) )    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $OFS = ','    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; $gen = &amp;quot;&amp;lt;&amp;quot; + [string](0..($count-1) | %{ &amp;quot;T&amp;quot;+$upperList[$_] }) + &amp;quot;&amp;gt;&amp;quot;&amp;#160;&amp;#160;&amp;#160;&amp;#160; &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public static bool operator==(Tuple$gen left, Tuple$gen right) {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return EqualityComparer&amp;lt;Tuple$gen&amp;gt;.Default.Equals(left,right); }&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;public static bool operator!=(Tuple$gen left, Tuple$gen right) {&amp;quot;    &lt;br /&gt;&amp;#160;&amp;#160;&amp;#160; &amp;quot;return !EqualityComparer&amp;lt;Tuple$gen&amp;gt;.Default.Equals(left,right); }&amp;quot;    &lt;br /&gt;}&lt;/p&gt;  &lt;p&gt;In addition to the methods, the Tuple class generation must be changed to implement IEquatable&amp;lt;Tuple&amp;lt;&amp;gt;&amp;gt;.&amp;#160; &lt;/p&gt;  &lt;p&gt;Some will notice that the implementation forces the equality comparison to be against a Tuple&amp;lt;T&amp;gt; vs an ITuple&amp;lt;T&amp;gt;.&amp;#160; There are a couple of reasons for this. &lt;/p&gt;  &lt;ol&gt;   &lt;li&gt;I have come up against specific scenarios where I wanted to compare Tuple&amp;lt;T&amp;gt; but not ITuple&amp;lt;T&amp;gt;.&amp;#160; This is not saying they don't exist (they do).&amp;#160; But I prefer to leave an implementation until I find a justification for implementing it.&amp;#160; &lt;/li&gt;    &lt;li&gt;By constraining to IEquatable&amp;lt;Tuple&amp;lt;T&amp;gt;&amp;gt; we are always comparing apples to apples.&amp;#160; If you try and perform an Equals against ITuple&amp;lt;TA&amp;gt; you're leaving yourself open to comparing apples and oranges.&amp;#160; Since ITuple&amp;lt;TA,TB&amp;gt; implements ITuple&amp;lt;TA&amp;gt; it is a valid target for the overload.&amp;#160; This type of equality seems scenario dependent and as such I left it out for the time.&amp;#160; Note with our current implementation it would be very easy to come back and add this later.&lt;/li&gt;    &lt;li&gt;To make #2 even stranger, once MutableTuples are implemented an implemantation of IEquatable&amp;lt;ITuple&amp;lt;TA&amp;gt;&amp;gt; might actually be comparing Tuple&amp;lt;TA,TB,TC&amp;gt; to MutableTuple&amp;lt;TA&amp;gt;.&amp;#160; &lt;/li&gt; &lt;/ol&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7193911" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jaredpar/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Generics/default.aspx">Generics</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Tuple/default.aspx">Tuple</category></item><item><title>Tuples Part 4: Interface</title><link>http://blogs.msdn.com/jaredpar/archive/2008/01/10/tuples-part-4-interface.aspx</link><pubDate>Thu, 10 Jan 2008 23:59:49 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7062421</guid><dc:creator>Jared Parsons</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/jaredpar/comments/7062421.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jaredpar/commentrss.aspx?PostID=7062421</wfw:commentRss><wfw:comment>http://blogs.msdn.com/jaredpar/rsscomments.aspx?PostID=7062421</wfw:comment><description>&lt;p&gt;Now we have a decent tuple generation script which produces a very usable set of tuple classes.&amp;nbsp; After awhile I ended up getting stuck because the tuples are not flexible enough.&amp;nbsp; It's not possible to use a 2 pair tuple where a 1 pair is expected even though it meets the requirements.&amp;nbsp; &lt;/p&gt;&lt;pre class="code"&gt;            Process(&lt;span style="color: rgb(43,145,175)"&gt;Tuple&lt;/span&gt;.Create(&lt;span style="color: rgb(163,21,21)"&gt;"foo"&lt;/span&gt;));
            Process(&lt;span style="color: rgb(43,145,175)"&gt;Tuple&lt;/span&gt;.Create(&lt;span style="color: rgb(163,21,21)"&gt;"foo"&lt;/span&gt;, 42));

        &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;void&lt;/span&gt; Process&amp;lt;TA&amp;gt;(&lt;span style="color: rgb(43,145,175)"&gt;ITuple&lt;/span&gt;&amp;lt;TA&amp;gt; tuple)
        {
            
        }&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;I considered two approaches to this problem; inheritance and interface.&amp;nbsp; I debated the inheritance one for awhile.&amp;nbsp; I couldn't convince myself one way or another if a Tuple&amp;lt;int,int&amp;gt; was a Tuple&amp;lt;int&amp;gt; or merely behaved like one.&amp;nbsp; Also once we introduce a MutableTuple class inheritance won't fix the problem (unless you introduce nasty shadowing variables).&amp;nbsp; Instead I opted for an interface based approach.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;In addition to defining the basic interface I added two methods to the base most interface.&amp;nbsp; These methods allow methods to operate on tuples in generic ways regardless of the pair count.&amp;nbsp; &lt;/p&gt;&lt;pre class="code"&gt;    &lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; Count { &lt;span style="color: rgb(0,0,255)"&gt;get&lt;/span&gt;; }
    &lt;span style="color: rgb(0,0,255)"&gt;object&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;this&lt;/span&gt;[&lt;span style="color: rgb(0,0,255)"&gt;int&lt;/span&gt; index] { &lt;span style="color: rgb(0,0,255)"&gt;get&lt;/span&gt;; }&lt;/pre&gt;
&lt;p&gt;Generating the implementation is straight forward at this point considering the past solutions.&amp;nbsp; You'll also have to alter the class definition to inherit from the appropriate ITuple interface.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Hopefully by now it's becoming clear why having a script to regenerate the large code base is a good idea.&amp;nbsp; It's easy to make sweeping changes to your implementation.&lt;/p&gt;
&lt;p&gt;function script:Gen-ITuple &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; param ( [int] $count = $(throw "Need a count") ) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $OFS = ',' &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $gen = "&amp;lt;" + [string](0..($count-1) | %{ "T"+$upperList[$_] }) + "&amp;gt;"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $base = "" &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; if ( $count -ne 1 ) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $baseGen = "&amp;lt;" + [string](0..($count-2) | %{ "T"+$upperList[$_] }) + "&amp;gt;"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $base = ": ITuple$baseGen" &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; else &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; { &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; $base = ": ITuple" &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "public interface ITuple$gen $base {" &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "T{0} {0} {{ get; }}" -f $upperList[$count-1]&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "}" &lt;br&gt;} &lt;/p&gt;
&lt;p&gt;function script:Gen-TupleAccess &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; param ( [int] $count = $(throw "Need a count") ) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "public int Count { get { return $count; } }" &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "public object this[int index] { get { switch (index){ " &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0..($count-1) | %{ "case $($_): return m_$($lowerList[$_]);" } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "default: throw new InvalidOperationException(""Bad Index"");" &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "} } }" &lt;br&gt;}&lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7062421" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jaredpar/archive/tags/PowerShell/default.aspx">PowerShell</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Tuple/default.aspx">Tuple</category></item><item><title>Tuples Part 3: Type Inference Friendly Constructor</title><link>http://blogs.msdn.com/jaredpar/archive/2008/01/07/tuples-part-3-type-inference-friendly-constructor.aspx</link><pubDate>Mon, 07 Jan 2008 19:38:11 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:7017156</guid><dc:creator>Jared Parsons</dc:creator><slash:comments>1</slash:comments><comments>http://blogs.msdn.com/jaredpar/comments/7017156.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jaredpar/commentrss.aspx?PostID=7017156</wfw:commentRss><wfw:comment>http://blogs.msdn.com/jaredpar/rsscomments.aspx?PostID=7017156</wfw:comment><description>&lt;p&gt;&lt;a href="http://blogs.msdn.com/jaredpar/archive/2008/01/04/tuples-part-2-basic-structure.aspx"&gt;Last time&lt;/a&gt; we were left with a constructor that required us to explicitly specify generic parameters.&amp;nbsp; This is not always easy or possible.&amp;nbsp; We'll now alter the script to generate a constructor which utilizes type inference to create a Tuple.&amp;nbsp; In addition, all tuples will use the same overloaded method making the creation uniform.&amp;nbsp; &lt;/p&gt; &lt;p&gt;The best way to use type inference to create a generic argument is through static methods.&amp;nbsp; In C# and VB it's legal to define a non-generic class with the same name as a generic class.&amp;nbsp; I tend to create a non-generic class with a static Create method that takes advantage of type inference.&amp;nbsp; For tuples the method will look like the following. &lt;/p&gt;&lt;pre class="code"&gt;&lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;partial&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;class&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;Tuple
&lt;/span&gt;{
    &lt;span style="color: rgb(0,0,255)"&gt;public&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;static&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;Tuple&lt;/span&gt;&amp;lt;TA&amp;gt; Create&amp;lt;TA&amp;gt;(TA a)
    { 
        &lt;span style="color: rgb(0,0,255)"&gt;return&lt;/span&gt; &lt;span style="color: rgb(0,0,255)"&gt;new&lt;/span&gt; &lt;span style="color: rgb(43,145,175)"&gt;Tuple&lt;/span&gt;&amp;lt;TA&amp;gt;(a); 
    }
}&lt;/pre&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;
&lt;p&gt;This allows us to write the following code.&amp;nbsp; &lt;/p&gt;&lt;pre class="code"&gt;            &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; tuple = &lt;span style="color: rgb(43,145,175)"&gt;Tuple&lt;/span&gt;.Create(&lt;span style="color: rgb(163,21,21)"&gt;"foo"&lt;/span&gt;);&lt;/pre&gt;
&lt;p&gt;Partial classes are used because we will be generating one per Tuple class that we create.&amp;nbsp; It's just easier to script it this way.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;The method is very straight forward.&amp;nbsp; We need one new additional string for the arguments to the constructor.&amp;nbsp; It's created along the same line as the previous strings.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;function script:Gen-InferenceConstructor &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; param ( [int] $count = $(throw "Need a count") ) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $OFS = ',' &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $gen = "&amp;lt;" + [string](0..($count-1) | %{ "T"+$upperList[$_] }) + "&amp;gt;"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $list = [string](0..$($count-1) | %{ "T{0} {1}" -f $upperList[$_],$lowerList[$_] }) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $argList = [string](0..$($count-1) | %{ $lowerList[$_] }) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "public partial class Tuple {" &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "public static Tuple$gen Create$gen($list) { return new Tuple$gen($argList); } " &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "}" &lt;br&gt;} &lt;/p&gt;
&lt;p&gt;Now just add a call to this function in Get-Tuple and the code is now inference friendly.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;Next up is defining an interface for tuples that will allow us to treat a Tuple&amp;lt;2&amp;gt; as a Tuple&amp;lt;1&amp;gt;.&amp;nbsp; Both have an "A" property and should be able to be used in a generic way.&amp;nbsp; &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=7017156" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jaredpar/archive/tags/PowerShell/default.aspx">PowerShell</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Type+Inference/default.aspx">Type Inference</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Tuple/default.aspx">Tuple</category></item><item><title>Tuples Part 2: Basic Structure</title><link>http://blogs.msdn.com/jaredpar/archive/2008/01/04/tuples-part-2-basic-structure.aspx</link><pubDate>Fri, 04 Jan 2008 23:42:56 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6983151</guid><dc:creator>Jared Parsons</dc:creator><slash:comments>3</slash:comments><comments>http://blogs.msdn.com/jaredpar/comments/6983151.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jaredpar/commentrss.aspx?PostID=6983151</wfw:commentRss><wfw:comment>http://blogs.msdn.com/jaredpar/rsscomments.aspx?PostID=6983151</wfw:comment><description>&lt;p&gt;&lt;a href="http://blogs.msdn.com/jaredpar/archive/2008/01/03/tuples-part-1.aspx"&gt;Part 1 of the series&lt;/a&gt; outlined the basic structure of the tuple.&amp;nbsp; This entry will produce a PowerShell script that will generate N tuple classes containing 1-N name value pairs.&amp;nbsp; &lt;/p&gt; &lt;p&gt;The first step is to get a few script variables defined.&amp;nbsp; All of the names used in the tuples will be lower and upper case single characters tied to a specific index.&amp;nbsp; To make the script a bit shorter we will define indexable arrays up front for the letters.&amp;nbsp;&amp;nbsp; We'll also grad the tuple count.&lt;/p&gt; &lt;p&gt;$script:tupleCount = [int]$args[0] &lt;br&gt;$script:lowerList = 0..25 | %{ [char]([int][char]'a'+$_) } &lt;br&gt;$script:upperList = 0..25 | %{ [char]([int][char]'A'+$_) }&lt;/p&gt; &lt;p&gt;All of the functions in this script will output an array of strings into the PowerShell pipeline.&amp;nbsp; One of the neat/confusing features of PowerShell is that values that are not directly used in a function are passed onto the pipeline.&amp;nbsp; This will conveniently allow us to type in literal code and hopefully increase readability.&amp;nbsp; &lt;/p&gt; &lt;p&gt;Now for the function that generates a property.&amp;nbsp; The tuples will be immutable by default as such we will generate private read only fields and simple getters.&amp;nbsp; &lt;/p&gt; &lt;p&gt;It would also be just as plausible to skip the property here and instead produce a read only public field.&amp;nbsp; Later on we will be altering the tuples to be used in a generic fashion through interfaces.&amp;nbsp; Interfaces cannot define fields and instead we will need properties.&amp;nbsp; &lt;/p&gt; &lt;p&gt;function script:Gen-Property &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; param ( [int] $index&amp;nbsp; = $(throw "Need an index") ) &lt;br&gt;@" &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; private readonly T{0} m_{1}; &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; public T{0} {0} {{ get {{ return m_{1}; }} }} &lt;/p&gt; &lt;p&gt;"@ -f $upperList[$index],$lowerList[$index] &lt;br&gt;}&lt;/p&gt; &lt;p&gt;Next up we need to define a constructor.&amp;nbsp; All of the fields in the tuple are read only so we must define a constructor for the consumer (otherwise the tuples would be useless).&amp;nbsp; &lt;/p&gt; &lt;p&gt;Generating the parameter list string would be tedious in most languages but PowerShell makes it a snap.&amp;nbsp; When converting an array of strings into a single string the individual strings will be combined with the value of the *** $OFS variable (default is space).&amp;nbsp; We can switch this to a comma and provide a quick pipeline for the parameter list.&amp;nbsp; &lt;/p&gt; &lt;p&gt;function script:Gen-Constructor &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; param ( [int] $count = $(throw "Need a count") ) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $OFS = ',' &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $list = [string](0..$($count-1) | %{ "T{0} {1}" -f $upperList[$_],$lowerList[$_] }) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "public Tuple($list) {" &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0..($count-1) | %{ "m_{0} = {0};" -f $lowerList[$_] } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "}" &lt;br&gt;} &lt;/p&gt; &lt;p&gt;Now that we have the basics we can generate the class.&amp;nbsp; We'll use the same $OFS trick to generate the generic argument list here. &lt;/p&gt; &lt;p&gt;function script:Get-Tuple &lt;br&gt;{ &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; param ( [int] $count ) &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $OFS = ',' &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; $gen = "&amp;lt;" + [string](0..($count-1) | %{ "T"+$upperList[$_] }) + "&amp;gt;"&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp; &lt;/p&gt; &lt;p&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "public sealed class Tuple$gen {" &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; 0..($count-1) | %{ Gen-Property $_ } &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; Gen-Constructor $count &lt;br&gt;&amp;nbsp;&amp;nbsp;&amp;nbsp; "}" &lt;br&gt;}&lt;/p&gt; &lt;p&gt;Now all that's left is processing the arguments&lt;/p&gt; &lt;p&gt;[string](0..($tupleCount-1) | %{ Get-Tuple ($_+1) })&lt;/p&gt; &lt;p&gt;Next step is to generate code that is more type inference friendly.&amp;nbsp; &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6983151" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jaredpar/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Tuple/default.aspx">Tuple</category></item><item><title>Tuples Part 1</title><link>http://blogs.msdn.com/jaredpar/archive/2008/01/03/tuples-part-1.aspx</link><pubDate>Thu, 03 Jan 2008 19:25:51 GMT</pubDate><guid isPermaLink="false">91d46819-8472-40ad-a661-2c78acb4018c:6969362</guid><dc:creator>Jared Parsons</dc:creator><slash:comments>6</slash:comments><comments>http://blogs.msdn.com/jaredpar/comments/6969362.aspx</comments><wfw:commentRss>http://blogs.msdn.com/jaredpar/commentrss.aspx?PostID=6969362</wfw:commentRss><wfw:comment>http://blogs.msdn.com/jaredpar/rsscomments.aspx?PostID=6969362</wfw:comment><description>&lt;p&gt;A tuple in computer science can be described as a set of name/value pairs.&amp;nbsp; In some cases it can be described as simply a set of values that are accessible via an index [1].&amp;nbsp; Previously I discussed how to create a &lt;a href="http://blogs.msdn.com/jaredpar/archive/2007/11/29/tuples-in-powershell.aspx"&gt;Tuple inside of PowerShell&lt;/a&gt;.&amp;nbsp; This series will focus on the use of Tuples in DotNet and how to use PowerShell to generate DotNet code.&amp;nbsp; &lt;/p&gt; &lt;p&gt;This series will also distinguish between mutable and immutable tuples.&amp;nbsp; As DotNet is shifting it's focus on parallel programming, immutable types are becoming more important.&amp;nbsp; Therefore this serious will focus on Tuples as immutable types and later examine mutable tuples.&lt;/p&gt; &lt;p&gt;In Visual Studio 2005, both C# and VB acquired tuples as a part of the programming language in the form of Anonymous Types.&amp;nbsp; These fit all of the properties of a tuple.&amp;nbsp; The one difference is in VB, anonymous types are mutable by default.&amp;nbsp; This can be changed though by using the &lt;strong&gt;Key&lt;/strong&gt; keyword.&amp;nbsp; &lt;/p&gt; &lt;p&gt;However anonymous types are lacking one quality which severely lessens their usefulness.&amp;nbsp; &lt;a href="http://blogs.msdn.com/jaredpar/archive/2007/10/01/casting-to-an-anonymous-type.aspx"&gt;Their type cannot be described&lt;/a&gt;.&amp;nbsp; This prevents them from being used as parameters, fields, generic parameters [2] etc ...&amp;nbsp; Unless you use late binding or terribly awkward casts this is limiting.&amp;nbsp; &lt;/p&gt; &lt;p&gt;To get around this, we will be defining a set of generic tuple class supporting 1-N name value pairs.&amp;nbsp; The great downside is because we will be predefining these types the names in the name value pair will be fixed.&amp;nbsp; We will be using A-N for 1-N pairs. &lt;/p&gt; &lt;p&gt;This is very limiting in itself because it's reducing the expressiveness of a type.&amp;nbsp; Anonymous types are much more expressive since they have names.&amp;nbsp; Now types will have properties A,B, etc ...&amp;nbsp; &lt;/p&gt; &lt;p&gt;For me this still works.&amp;nbsp; In my code, I only end up using tuples when I need to pass data around between tightly coupled classes, or just within the same class.&amp;nbsp;&amp;nbsp; Since the creation and use are so close loosing the full expressiveness of the name is not that limiting.&amp;nbsp; &lt;/p&gt; &lt;p&gt;In addition, our tuple implementation will leverage type inference as much as possible such that the following code can be written.&lt;/p&gt;&lt;a href="http://11011.net/software/vspaste"&gt;&lt;/a&gt;&lt;pre class="code"&gt;            &lt;span style="color: rgb(0,0,255)"&gt;var&lt;/span&gt; tuple = &lt;span style="color: rgb(43,145,175)"&gt;Tuple&lt;/span&gt;.Create(&lt;span style="color: rgb(163,21,21)"&gt;"foo"&lt;/span&gt;);
            &lt;span style="color: rgb(43,145,175)"&gt;Console&lt;/span&gt;.WriteLine(tuple.A);&lt;/pre&gt;
&lt;p&gt;Why write a script to generate these classes?&amp;nbsp; Wouldn't it just be easier to just do this by hand???&amp;nbsp; Yes and no.&amp;nbsp; If you are doing a fixed set of short used classes then yes, do it by hand.&amp;nbsp; These scripts evolved out of my use of tuples.&amp;nbsp; Once I would settle on a structure and I would think of a new feature I needed.&amp;nbsp; Typically I have tuples defined up to 5 fields.&amp;nbsp; Retyping out a new feature got tiresome and error prone.&amp;nbsp; With a scripting solution I could add a new feature and tests in just a few minutes.&amp;nbsp; The series is very representative of the way my solution changed over time.&amp;nbsp; Simple at first but I added features as the situation dictated.&amp;nbsp; Having a scripting solution saved me a lot of time.&lt;/p&gt;
&lt;p&gt;Next up, generating the basic structure.&amp;nbsp; &lt;/p&gt;
&lt;p&gt;[1] In this case, the index just becomes the name and hence a name/value pair. &lt;/p&gt;&lt;img src="http://blogs.msdn.com/aggbug.aspx?PostID=6969362" width="1" height="1"&gt;</description><category domain="http://blogs.msdn.com/jaredpar/archive/tags/PowerShell/default.aspx">PowerShell</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/VB/default.aspx">VB</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/C_2300_/default.aspx">C#</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Threading/default.aspx">Threading</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Immutable/default.aspx">Immutable</category><category domain="http://blogs.msdn.com/jaredpar/archive/tags/Tuple/default.aspx">Tuple</category></item></channel></rss>