В официальном документе упоминается, что Length является псевдонимом для Count, однако я нашел один случай, когда они ведут себя по-разному. Кроме того, если я заменю метод ForEach на ForEach-Object, Length будет выдавать 3. Может ли кто-нибудь объяснить это?

> (1..3).ForEach({$_}).Length
1
1
1
> (1..3).ForEach({$_}).Count
3

Elderry

Ответов: 1

Ответы (1)

.Length и .Count являются псевдонимами друг друга и представляют собой так называемые внутренние члены (свойства), которые PowerShell добавляет к большинству объектов в интересах унификации обработки скаляров и коллекций (см. этот ответ для справки).

.

Исключением являются объекты типов, которые PowerShell рассматривает как коллекции, то есть объекты, которые он автоматически перечисляет в конвейере, что включает экземпляры типа [System.Collections.ObjectModel.Collection[psobject]], которые возвращает метод .ForEach() массива.

PowerShell не добавляет свойства .Length и .Count к экземплярам того, что он считает коллекциями, поскольку предполагает, что они имеют такие свойства самостоятельно, тип-нативно, предполагается, что они реализованы эффективно (вместо того, чтобы PowerShell приходилось выполнять перечисление и подсчет элементов).

.

Это разумное предположение типично для .Count, но редко для .Length (массивы (System.Array) - единственный яркий пример, где .Length существует и возвращает количество элементов).

Таким образом, обычно лучше использовать .Count, а не .Length.

.

Когда вы обращаетесь к .Length в экземпляре типа, который PowerShell считает коллекцией, но у этого типа нет такого свойства, присущего типу, PowerShell выполняет перечисление членов:

  • То есть перечисляет коллекцию и возвращает значения свойств элементов' .Length.

    .
  • В вашем случае, поскольку элементы являются скалярами (единичными объектами [int]), они до имеют свойство intrinsic .Length, которое в случае скаляра всегда возвращает 1.

  • .

Так что:

(1..3).ForEach({$_}).Length

это фактически то же самое, что:

(1..3).ForEach({ $_.Length })

Вышесказанное объясняет вывод (1, 1, 1). Напротив, [System.Collections.ObjectModel.Collection[psobject]] имеет свойство type-native .Count, которое возвращает количество элементов, как и ожидалось.


Основная информация:

Примечание:

  • Только те типы, которые PowerShell не считает коллекциями, получают присущие им свойства .Count и .Length.

  • И наоборот, типы, которые считаются коллекциями, могут иметь или не иметь ни одного, ни другого, ни обоих таких свойств нативно по типу, и в отсутствие нативного по типу свойства вместо него выполняется перечисление членов.

    .
    • Примечательными примерами типов, у которых ни то, ни другое свойство не является типовым, являются ленивые перечисления; например, [Linq.Enumerable]::Range(1,3).Count дает 1, 1, 1.
    • .

Какие типы .NET PowerShell считает коллекциями и поэтому автоматически перечисляет в конвейере:

  • Любой тип, реализующий IEnumerable / IEnumerable`1 .NET интерфейс(ы)

    .
    • За исключением следующих, которые не автоматически перечисляются:

      • IDictionary / IDictionary`2, который включает [hashtable] (@{ ....}, как литерал) и его упорядоченный родственник, OrderedDictionary ([ordered] @{ ...}, как литерал)

        .
      • XmlNode, базовый тип для [xml] (XmlDocument)

      • Strings (String); обратите внимание, что 'foo'.Count равно 1 (свойство, отражающее, что строка считается скаляром (единицей)), тогда как 'foo'.Length равно 3 (свойство типа, возвращающее количество символов).

        .
  • Дополнительно, System.Data.DataTable (которая сама не реализует IEnumerable, только ее свойство .Rows).

    .

2022 WebDevInsider