Skip to content

Recommend using Count to retrieve the number of elements in an in-memory collection #11614

@surfingoldelephant

Description

@surfingoldelephant

Prerequisites

  • Existing Issue: Search the existing issues for this repository. If there is an issue that fits your needs do not file a new one. Subscribe, react, or comment on that issue instead.
  • Descriptive Title: Write the title for this issue as a short synopsis. If possible, provide context. For example, "Document new Get-Foo cmdlet" instead of "New cmdlet."

PowerShell Version

5.1, 7.2, 7.3, 7.4

Summary

For consistency in PowerShell, accessing the Count property should be encouraged as the preferred method to retrieve the number of elements in a collection, especially for scenarios in which it's unknown if zero, one or multiple objects are yielded.

Exceptions exist, but as a general rule of thumb, using Count provides a far more consistent experience in PS over Length.

Details

  • Count is widely available to PowerShell-noteworthy collection types and thus aids PowerShell's unified scalar/collection handling better. Length is, for the most part, limited to arrays.
  • Array (and its derivatives) have both a Count and Length property. In PS, there is no significant difference between using either.
  • However, the following notable collection types only have a Count, not a Length.
    • List<T>: A common general purpose collection type used by PS users and endorsed officially.
      $list = [Collections.Generic.List[object]]::new((1, 2, 3))
      $list.Count # 3
      
      # No Length, so member-access enumeration applies Length access to each element.
      $list.Length # 1, 1, 1
    • ArrayList: Used extensively throughout PS (remoting/job/mini-shell data marshalling, -ErrorVariable, -OutVariable, $Error, etc), albeit usage in new code is not recommended.
      Get-Item foo, bar, baz -ErrorAction SilentlyContinue -ErrorVariable errs
      
      $errs.Count  # 3
      $errs.Length # 1, 1, 1
    • Collection<T>: Used by the intrinsic ForEach()/Where() methods and extensively in the [powershell] API.
      $collection = (1, 2, 3).ForEach{ $true }
      
      $collection.Count  # 3
      $collection.Length # 1, 1, 1
  • Length is particularly problematic with strings and FileInfo (both have a type-native Length) when a result could be one or multiple instances and typical pipeline semantics are in play.
    $result1 = 'foo', (, ('foo', 'bar')) | Get-Random
    $result.Length # Could be 2 or, unexpectedly in this context, 3 (length of the string)
    $result.Count  # Could 1 or 2, as expected
    
    $result2 = Get-ChildItem -Path foo* -File
    $result2.Length # Could be 0, 2+ or, unexpectedly in this context, the size of a file
    $result2.Count  # Could be 0, 1 or 2+, as expected
    
    # @(...) is a natural fit here, but is less likely to be considered by newer PS users.

Notes:

  • PS does not intrinsicly make Count/Length available to collections, hence the disparity between the two properties.
  • Collections.IDictionary-implementing dictionaries are special-cased as scalar, so have a type-native Count and intrinsic Length. Types that only implement the generic version are treated as a collection, so have a type-native Count but no Length. In both cases, Count refers to the number of key/value pairs.
  • The argument of Count vs Length concerns in-memory (fully collected) collections, not scenarios in which streaming is preferable.

Proposed Content Type

About Topic

Related Articles

https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_intrinsic_members#properties
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_arrays#properties-of-arrays
https://learn.microsoft.com/en-us/powershell/module/microsoft.powershell.core/about/about_properties#examples

Metadata

Metadata

Assignees

Labels

area-aboutArea - About_ topicsissue-doc-ideaIssue - request for new content

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions