问题
A System.IO.FileInfo has a Target member.
Using Get-Item -Path * -Include 't.txt' | Get-Member shows it to have a Target member that is a CodeProperty.
Using GetType() shows it to be a List`1
C:>Get-Item -Path * -Include 't.txt' | ForEach-Object { $_.Target.GetType() }
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True List`1 System.Object
C:>Get-Item -Path * -Include 't.txt' | % { $_.Target.GetType() | % { $_.FullName } }
System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]
回答1:
vonPryz has provided the crucial pointer in a comment: List`1 is .NET's representation of a generic type named List with arity (`) 1, i.e., a generic type with 1 type parameter.
(The use of ` in this context is unrelated to PowerShell's use of ` as the escape character).
In your case, System.Collections.Generic.List`1[[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]] indicates that the generic type was closed (instantiated) with type System.String.
Leaving the assembly qualification aside (mscorlib, Version = ...), the equivalent PowerShell representation is System.Collections.Generic.List`1[[string]], which can be simplified in two ways, however:
- The arity indicator,
`1, can be omitted, given that the arity is implied by the type argument in[...],[string]. - Given that there's only 1 type parameter, you can omit the outer
[...]around the type argument list.
Therefore, you can use just System.Collections.Generic.List[string], or, expressed as a PowerShell type literal ([...]), [System.Collections.Generic.List[string]]
Optional reading: Shortening type names and literals in PowerShell:
[System.Collections.Generic.List[string]] is a bit unwieldy, and there are two ways to shorten it:
PowerShell allows you omit the
System.part of the namespace for any type, so[Collections.Generic.List[string]]works too.PowerShell v5+ offers the
using namespacestatement, analog to C#'susingstatement:# Note: # * `using namespace` must be at the *start* of the script (potentially # preceded by other `using` statements and comments only) # * The 'System.' part of a namespace must *not* be omitted. using namespace System.Collections.Generic [List[string]] # short for: [System.Collections.Generic.List[string]]
Additionally, PowerShell has built-in type accelerators for certain often-used types, which are single-component names that refer to specific types without needing to specify their namespace of origin; e.g., [xml] is a type accelerator for [System.Xml.XmlDocument].
This TechNet blog post shows that you can use the following command to list all built-in type accelerators:
[psobject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::
get.GetEnumerator() | Sort-Object Key
As TheIncorrigible1 points out, you can even define your own type accelerators with the ::Add() method; e.g., the following command defines [cmdinfo] as an accelerator for type [System.Management.Automation.CommandInfo]:
[psobject].Assembly.GetType("System.Management.Automation.TypeAccelerators")::
Add('cmdinfo', [System.Management.Automation.CommandInfo])
The new accelerator will be available session-globally (but only for the current session), even if the call is made from a child scope.
That said, there's a good reason not to do this:
System.Management.Automation.TypeAcceleratorsis not a public type, so it isn't part of PowerShell's public API, and therefore not guaranteed to be there (in its present form) in the future.Therefore, the
using namespaceapproach is preferable.
来源:https://stackoverflow.com/questions/54961238/what-is-a-list1-object