Итак, я создаю массив, вызываю GetType() и (разумно) получаю ответ Object[]. Однако, если я даю ему плохой метод, я получаю тип 0-го элемента в сообщении об ошибке.
Просто пытаюсь понять Powershell больше - я предполагаю, что это связано с тем, что Powershell разворачивает массив в случае, если он не находит метод в массиве, а затем также терпит неудачу в 0-м массиве, который выдает полную ошибку?
PS C:\Users\x> $i = @(1)
PS C:\Users\x> $i.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
PS C:\Users\x> $i.HerpDerp()
InvalidOperation: Method invocation failed because [System.Int32] does not contain a method named 'HerpDerp'.
PS C:\Users\x> $a = @("hi")
PS C:\Users\x> $a.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
PS C:\Users\x> $a.HerpDerp()
InvalidOperation: Method invocation failed because [System.String] does not contain a method named 'HerpDerp'.
PS C:\Users\x> $m = @("hi",1)
PS C:\Users\x> $m.GetType()
IsPublic IsSerial Name BaseType
-------- -------- ---- --------
True True Object[] System.Array
PS C:\Users\x> $m.HerpDerp()
InvalidOperation: Method invocation failed because [System.String] does not contain a method named 'HerpDerp'.
В значительной степени то, что вы указали в вопросе, верно, это также объясняется в документе «Перечисление членского доступа»: «Во время перечисления членского доступа для метода оператор пытается вызвать метод для каждого элемента в коллекции. Если какой-либо элемент в в коллекции нет указанного метода, оператор возвращает исключение MethodNotFound."
Спасибо! У меня было ощущение, что это было задумано, но я не мог понять, как понять, как называется механизм.



Соответствующая информация находится в комментариях, но я думаю, что ваш вопрос заслуживает ответа:
То, что вы видите, — это эффекты перечисления доступа к элементам, удобной функции PowerShell, где доступ к члену (свойству или методу) в массиве (спископодобной коллекции) неявно обращается к этому члену в его элементах, один за другим. , и возвращает результаты в виде массива, за исключением случаев, когда есть только один результат, который возвращается как есть;[1] например:
# Even though .Year is applied to the *array*, PowerShell returns
# the .Year property values from the two [datetime] instances that
# are the *elements* of that array; e.g., in 2023:
# @( 2023, 2022 )
@( (Get-Date), (Get-Date).AddYears(-1) ).Year
Это работает только в том случае, если указанный элемент не существует в самом массиве, поскольку собственный элемент массива имеет приоритет; например.:
# Returns 3, the *array's* .Length property value (count of elements),
# not the length of the strings stored in the array's elements.
@( 'foo', 'bar', 'baz' ).Length
Это также объясняет, почему $i.GetType() возвращает тип массива.
Когда применяется перечисление доступа к членам, поведение (по умолчанию) различается в зависимости от того, обращаетесь ли вы к свойству или методу:
Доступ к собственности:
Любой элемент массива, не имеющий указанного свойства, просто не участвует в выводе; если ни один элемент массива не имеет такого свойства, общий результат равен $null
# Outputs only 2023 (for instance), because [int] 42 has no .Year property.
@( (Get-Date), 42 ).Year
$null, оно включается в результаты.$null, если свойство не существует — см. GitHub issue #13752Доступ к методу:
Если какой-либо элемент массива не имеет метода с указанным именем — или если вызов метода приводит к исключению — возникает ошибка завершения оператора, что означает отсутствие успешного вывода и сообщается только об одной ошибке, а именно для первый элемент, у которого не было метода/вызвал исключение (это объясняет результаты ваших .HerpDerp() вызовов):
# !! Statement fails as a whole, because [int] (System.Int32)
# !! doesn't have a .ToShortDateString() method.
@( (Get-Date), 42 ).ToShortDateString()
Обратите внимание, что вышеизложенное подразумевает, что это не обязательно первый элемент, который вызывает ошибку завершения оператора, и если это не так, результаты вызовов более ранних элементов фактически отбрасываются. Это несколько проблематично, учитывая, что вызовы методов могут иметь побочные эффекты (и, возможно, не иметь вывода), и в этом случае вам может потребоваться определить постфактум, для каких элементов были успешно выполнены вызовы методов.
[1] In doing so, member-access enumeration mimics the behavior of PowerShell's pipeline, which may be surprising. See GitHub issue #6802 for a discussion.
Это связано с тем, что оператор вызова члена попытается вызвать содержащиеся элементы, если запрошенный элемент не найден в самом массиве — эта функция/поведение известно как перечисление доступа к члену