3

i'm trying to make System.Memory[char] .

[System.Memory[char]]::Memory([char],0,10) * says it can't find System.Memory type .

Also tried *

[System.Memory`3+[[char],0,10]]@()

Solution: The issue seems to be the .NET version used by the Powershell .

irvnriir
  • 673
  • 5
  • 14
  • As an aside re `\`` in PowerShell type literals, such as ``[System.Memory`1]`` (represented in C# as `System.Memory`): `` refers to the number of _type parameters_ in _generic .NET types_. Thus, [``[System.Memory`1]``](https://docs.microsoft.com/en-us/dotnet/api/system.memory-1) implies _one_ type parameter, which is correctly supplied as `[char]` in your first attempt: `[System.Memory[char]]` (which you could also express as ``[System.Memory`1[char]]``, but that is only necessary for accessing _nested_ types; see link). `` is unrelated to the _number of constructor arguments_. – mklement0 Mar 27 '22 at 17:07

1 Answers1

4

It is the static pseudo method ::new(), introduced in PowerShell v5, that provides access to a type's constructors.[1]

# Initialize a [System.Memory[char]] instance with 10 NUL (0x0) chars,
# from a [char[]] array.
[System.Memory[char]]::new(
  [char[]]::new(10)
)

Note: The two System.Memory`1 constructors both require a [char[]] array as an argument. The two additional arguments in the 3-parameter overload, start and length, must refer to a range of elements within that array.

The above simply creates a 10-element array to begin with (implicitly using NUL characters), obviating the need for the additional arguments.

If you wanted the input array to use a given character other than NUL, you could use something like , [char] 'x' * 10:
, [char] 'x' create a single-element array with char. 'x', which * 10 then replicates to return a 10-element array. Note that the array will be [object[]]-typed, not [char[]]-typed, but it still works.


Note:

  • [System.Memory[char]]@() does not work, because in order for PowerShell to translate this cast to a single-parameter constructor call, the operand must be a [char[]] array:

    • [System.Memory[char]] [char[]] @()
  • Fundamentally, the System.Memory`1 type is available only in .NET Core 2.1+ / .NET 5+.

    • The simplest way to check if the type is available in your PowerShell session is if [bool] $IsCoreClr returns $true - in other words: you need to be running PowerShell (Core) 7+, the modern, cross-platform, install-on-demand edition of PowerShell.

[1] In earlier PowerShell versions you need to use the New-Object cmdlet, which uses argument(-parsing) mode, as all cmdlets do. As such, its syntax doesn't map cleanly onto the expression-mode syntax that is familiar from method/constructor calls, especially with respect to passing a single argument that is an array, as in this case:
New-Object System.Memory[char] -ArgumentList (, (New-Object char[] 10))
Note the need to wrap the array constructed by , [char] 0) * 10 in another array, namely a transitory one that is needed to make New-Object treat the original array as a single argument for the target constructor.
Additionally, ::new() performs better, though that will often not matter. See this answer for details.

mklement0
  • 382,024
  • 64
  • 607
  • 775
  • i did try that too, says can't find System.Memory type – irvnriir Mar 25 '22 at 23:10
  • @irvnriir, please see my update. There is indeed no `System.Memory` type, but there is `System.Memory\`1`, aka `System.Memory` – mklement0 Mar 25 '22 at 23:18
  • `[System.Runtime.InteropServices.RuntimeEnvironment]::GetSystemVersion()` outputs v4[..] , this is the reason ? isn't Windows Powershell always running on the .NET Framework 4.[..] ? – irvnriir Mar 25 '22 at 23:43
  • 1
    @irvnriir, this method seems to return a value that is frozen in time for backward compatibility. Use the following instead to see the true framework version: `[System.Runtime.InteropServices.RuntimeInformation]::FrameworkDescription`. Yes, Windows PowerShell runs on the legacy, Windows-only .NET Framework, whose latest and _last_ version is v4.8.x – mklement0 Mar 26 '22 at 01:39
  • the command doesn't work in this Powershell, tried also with `write-host` and `write-output` . – irvnriir Mar 26 '22 at 06:24
  • is said that it works on OSx . command for Win P -- [ink](https://stackoverflow.com/a/46829654/12669337) . – irvnriir Mar 26 '22 at 06:32
  • @irvnriir, [`[System.Runtime.InteropServices.RuntimeInformation]::FrameworkDescription`](https://learn.microsoft.com/en-US/dotnet/api/System.Runtime.InteropServices.RuntimeInformation.FrameworkDescription) works in .NET Framework v4.7.1 and above, and therefore also on Windows. (and in .NET (Core) v1 and above). – mklement0 Mar 26 '22 at 14:31
  • @irvnriir, I've updated the answer with the following: The simplest way to check if the type is available in your PowerShell session is if `[bool] $IsCoreClr` returns `$true` - in other words: **you need to be running [_PowerShell (Core) 7+_](https://github.com/PowerShell/PowerShell/blob/master/README.md)**, the modern, cross-platform, install-on-demand edition of PowerShell. – mklement0 Mar 26 '22 at 14:37
  • the article you've linked is wrong, since i have 4.8 . – irvnriir Mar 28 '22 at 08:10
  • @irvnriir, the premise of your question is that you want to use the `System.Memory\`1` type. My answer and its links are telling you that you need .NET _Core_ 2.1 or higher to use this type, and therefore PowerShell _Core_. What is wrong is your attempt to use the type from .NET _Framework_ 4.8, which implies the legacy _Windows PowerShell_ edition. – mklement0 Mar 28 '22 at 11:55
  • @mclement0 ... i mean `[System.Runtime.InteropServices.RuntimeInformation]::FrameworkDescription` – irvnriir Mar 29 '22 at 12:32
  • @irvnriir, the previously linked docs state that this property is available in "4.7.1, 4.7.2, 4.8" (as well as in .NET _Core_ since v1), and it works in my v4.8-based Windows PowerShell sessions. Does it not work for you? – mklement0 Mar 29 '22 at 13:12