What is a List`1 object?

蓝咒 提交于 2021-02-07 04:24:12

问题


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 namespace statement, analog to C#'s using statement:

      # 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.TypeAccelerators is 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 namespace approach is preferable.



来源:https://stackoverflow.com/questions/54961238/what-is-a-list1-object

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!