I had Windows PowerShell script that initialized a queue like this:
$queue = New-Object System.Collections.Queue<byte>
The code was working fine in Windows PowerShell, but it does not in PowerShell [Core]. It fails with
Cannot find type [System.Collections.Queue<byte>]: verify that the assembly containing this type is loaded.
When fixing the script for PowerShell [Core], I've realized that:
System.Collections.Queue is not a generic type (System.Collections.Generic.Queue is).[], not <>.So the correct code, both in Windows PowerShell and PowerShell [Core] is:
$queue = New-Object System.Collections.Generic.Queue[byte]
But now I wonder what was my original code actually doing. What magic is behind that? Is my new code a real equivalent of the original?
The magic is that Windows PowerShell simply quietly ignores the <byte> part; in fact, it doesn't matter what is inside < and >, and more generally, there are several characters that can start a suffix that is ignored, such as !, @ and %.
In other words: this is a bug, and it has since been fixed in PowerShell (Core) 7+, which properly interprets the whole argument as the type name.
And, as you note:
Generic type arguments always require enclosure in [...] in PowerShell as well as the underlying, language-agnostic .NET APIs.
[...] enclosure is also used for PowerShell's type literals, which are a superset of the notation understood by the .NET APIs, as discussed in this answer.
Because in v5+ the static ::new() method can be used on type literals as a method-syntax alternative to New-Object, your generic-queue construction command can also be written as:
$queue = [System.Collections.Generic.Queue[byte]]::new()
::new() is preferable to New-Object calls for several reasons:
[psobject] wrappers that New-Object wraps newly constructed objects in, which are usually invisible and benign, but on occasion cause problems - see this answer for an example.New-ObjectBy contrast, the <...> syntax is language-specific, as notably used in C#.
A type syntax in PowerShell is always [T], not <T>.
See e.g. Queue<T> Class…
Here <> are meta brackets: in Microsoft conception,
<Text inside angle brackets> means a placeholder for which you must supply a value.
The following example comes from PowerShell 5 under wt.exe (Windows Terminal):
PS D:\PShell> [System.Collections.Generic.Queue
Comparer<> IEqualityComparer<> LinkedListNode<>
Dictionary<> IList<> List<>
EqualityComparer<> IReadOnlyCollection<> Queue<>
HashSet<> IReadOnlyDictionary<> SortedDictionary<>
ICollection<> IReadOnlyList<> SortedList<>
IComparer<> ISet<> SortedSet<>
IDictionary<> KeyNotFoundException Stack<>
IEnumerable<> KeyValuePair<>
IEnumerator<> LinkedList<>
Class System.Collections.Generic.Queue[T]
As a picture:

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With