{"id":3657,"date":"2014-03-29T07:37:12","date_gmt":"2014-03-29T07:37:12","guid":{"rendered":"https:\/\/unknownerror.org\/index.php\/2014\/03\/29\/issue-using-framework-4-0-in-powershell-with-system-stringjoin-collection-of-common-programming-errors\/"},"modified":"2014-03-29T07:37:12","modified_gmt":"2014-03-29T07:37:12","slug":"issue-using-framework-4-0-in-powershell-with-system-stringjoin-collection-of-common-programming-errors","status":"publish","type":"post","link":"https:\/\/unknownerror.org\/index.php\/2014\/03\/29\/issue-using-framework-4-0-in-powershell-with-system-stringjoin-collection-of-common-programming-errors\/","title":{"rendered":"Issue using Framework 4.0 in Powershell with [system.string]::join-Collection of common programming errors"},"content":{"rendered":"<p>This is due to the new overloads to <code>string.Join<\/code> added in version 4 of the .NET framework:<\/p>\n<pre><code>PS&gt; [Environment]::Version.ToString()\n2.0.50727.5456\nPS&gt; [string]::Join.OverloadDefinitions\nstatic string Join(string separator, string[] value)\nstatic string Join(string separator, string[] value, int startIndex, int count)\n<\/code><\/pre>\n<pre><code>PS&gt; [Environment]::Version.ToString()\n4.0.30319.269\nPS&gt; [string]::Join.OverloadDefinitions\nstatic string Join(string separator, Params string[] value)\nstatic string Join(string separator, Params System.Object[] values)\nstatic string Join[T](string separator, System.Collections.Generic.IEnumerable[T] values)\nstatic string Join(string separator, System.Collections.Generic.IEnumerable[string] values)\nstatic string Join(string separator, string[] value, int startIndex, int count)\n<\/code><\/pre>\n<p>In .NET 2.0, the only applicable method overload takes a <code>string[]<\/code> as the second argument, so each character from <code>$word.ToCharArray()<\/code> is coerced to a string.<\/p>\n<pre><code>PS&gt; Trace-Command *Member* { [string]::Join( \"-\", $word.ToCharArray() ) } -PSHost\n...\nMemberResolution: Method argument conversion.\nMemberResolution:     Converting parameter \"-\" to \"System.String\".\nMemberResolution: Method argument conversion.\nMemberResolution:     Converting parameter \"System.Char[]\" to \"System.String[]\".\nMemberResolution: Calling Method: static string Join(string separator, string[] value)\n<\/code><\/pre>\n<p>In .NET 4, the <code>object[]<\/code> overload is preferred. Rather than boxing each character, the entire array is coerced to an object, sending a single-element object array to <code>string.Join<\/code>, which then has <code>ToString<\/code> called to produce the <code>\"System.Char[]\"<\/code> output.<\/p>\n<pre><code>Method argument conversion.\n    Converting parameter \"-\" to \"System.String\".\nMethod argument conversion.\n    Converting parameter \"System.Char[]\" to \"System.Object\".\nMethod argument conversion.\n    Converting parameter \"System.Object[]\" to \"System.Object[]\".\nCalling Method: static string Join(string separator, Params System.Object[] values)\n<\/code><\/pre>\n<p>To get the old behavior, you can insert a <code>[string[]]<\/code> cast to influence how the method is resolved (or in this case just use PowerShell&#8217;s <code>-join<\/code> operator, which works correctly everywhere :).<\/p>\n<pre><code>PS&gt; $word = 'test'\nPS&gt; [string]::Join( '-', $word.ToCharArray() )\nSystem.Char[]\nPS&gt; [string]::Join( '-', [string[]]$word.ToCharArray() )\nt-e-s-t\nPS&gt; [char[]]$word -join '-'\nt-e-s-t\n<\/code><\/pre>\n","protected":false},"excerpt":{"rendered":"<p>This is due to the new overloads to string.Join added in version 4 of the .NET framework: PS&gt; [Environment]::Version.ToString() 2.0.50727.5456 PS&gt; [string]::Join.OverloadDefinitions static string Join(string separator, string[] value) static string Join(string separator, string[] value, int startIndex, int count) PS&gt; [Environment]::Version.ToString() 4.0.30319.269 PS&gt; [string]::Join.OverloadDefinitions static string Join(string separator, Params string[] value) static string Join(string separator, Params [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[1],"tags":[],"class_list":["post-3657","post","type-post","status-publish","format-standard","hentry","category-uncategorized"],"_links":{"self":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/3657","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/comments?post=3657"}],"version-history":[{"count":0,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/posts\/3657\/revisions"}],"wp:attachment":[{"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/media?parent=3657"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/categories?post=3657"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/unknownerror.org\/index.php\/wp-json\/wp\/v2\/tags?post=3657"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}