question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Setting property values with the .ForEach() array method doesn't work with a single [pscustomobject] instance.

See original GitHub issue

Prerequisites

Steps to reproduce

.ForEach() has an overload that allows setting property values by name and (array of) property values.

This works in general, but unexpectedly not with a single [pscustomobject] instance (as later discovered, it does work with arrays of [pscustomobject] instances).

($obj = [pscustomobject] @{ p = 1 }).ForEach('p', 42)

Expected behavior

No output, and $obj.p should report 42 afterwards.

Actual behavior

1 - the current property value - is output, and the attempt to assign a new value is ignored.

Error details

No response

Environment data

PowerShell Core 7.3.0-preview.1

Visuals

No response

Issue Analytics

  • State:closed
  • Created 2 years ago
  • Comments:10 (2 by maintainers)

github_iconTop GitHub Comments

3reactions
SeeminglySciencecommented, Dec 23, 2021

Aside from the second one (which appears to be a very bizarre but separate binding bug) that all looks right. Where and ForEach always return a Collection<> regardless of the input.

1reaction
SeeminglySciencecommented, Dec 23, 2021

Looks like the binder is calling InvokeAdaptedMember instead of EnumerableOps.ForEach.

Here’s the Bind result for a scalar int:

if (((target is int) && (_version == 0)) && ((member is string) && (value is string)))
{
    return EnumerableOps.ForEach(
        Fake.Dynamic<Func<CallSite, IEnumerator, IEnumerator>>(PSEnumerableBinder.Get())(
            Fake.Dynamic<Func<CallSite, object[], IEnumerator>>(PSEnumerableBinder.Get())(
                new object[] { target })),
        member,
        new object[] { value });
}

(side note, dunno what’s up with the double enumerate there)

And here it is for a pscustomobject:

if ((((_version == 0) && (target is PSObject)) && ((PSObject.Base(target) == target) && (member is string))) &&
    (value is string))
{
    return PSInvokeMemberBinder.InvokeAdaptedMember(PSObject.Base(target), "ForEach", new object[] { member, value });
}
Read more comments on GitHub >

github_iconTop Results From Across the Web

Setting property values with the .ForEach() array method ...
Setting property values with the .ForEach() array method doesn't work with a single [pscustomobject] instance. #4182. Sign in to view logs.
Read more >
Prevent adding pscustomobject to array if already exists
GetHashCode() on a [pscustomobject] instance always yields the same value, irrespective of the instance's set of properties and values.
Read more >
Everything you wanted to know about PSCustomObject
In this article. Creating a PSCustomObject; Working with properties; Adding object methods; Using DefaultPropertySet (the long way); Function ...
Read more >
[SOLVED] Changing NoteProperty values in a collection of ...
I have a hashtable with a collection of properties and where the property values are a collection of PSCustomObjects.
Read more >
Array.prototype.forEach() - JavaScript - MDN Web Docs
Array.prototype.forEach(). The forEach() method of Array instances executes a provided function once for each array element.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found