Repository: PowerShell/PowerShell
File: src/System.Management.Automation/engine/runtime/Binding/Binders.cs (C#)

Code before:
                    return this.DeferForPSObject(args.Prepend(target).ToArray(), targetIsComObject: true).WriteToDebugLog(this);
                }
            }

            // Check if this is a COM Object
            DynamicMetaObject result;
            if (ComInterop.ComBinder.TryBindInvokeMember(this, _propertySetter, target, args, out result))
            {
                return result.UpdateComRestrictionsForPsObject(args).WriteToDebugLog(this);
            }

            var targetValue = PSObject.Base(target.Value);
            if (targetValue == null)
            {
                if (!_static && !_nonEnumerating)
                {
                    // As discussed with Bruce, the Where/ForEach operators should work on $null and return an empty collection.
                    // e.g. $null.Where{"I didn't run"} should return an empty collection
                    DynamicMetaObject emptyEnumerator = new DynamicMetaObject(
                        Expression.Call(Expression.NewArrayInit(typeof(object)), CachedReflectionInfo.IEnumerable_GetEnumerator),
                        BindingRestrictions.GetInstanceRestriction(Expression.Call(CachedReflectionInfo.PSObject_Base, target.Expression), null))
                        .WriteToDebugLog(this);
                    BindingRestrictions argRestrictions = args.Aggregate(BindingRestrictions.Empty, static (current, arg) => current.Merge(arg.PSGetMethodArgumentRestriction()));

                    if (string.Equals(Name, "Where", StringComparison.OrdinalIgnoreCase)
                    || string.Equals(Name, "PSWhere", StringComparison.OrdinalIgnoreCase))
                    {
                        return InvokeWhereOnCollection(emptyEnumerator, args, argRestrictions).WriteToDebugLog(this);
                    }

                    if (string.Equals(Name, "ForEach", StringComparison.OrdinalIgnoreCase)
                    || string.Equals(Name, "PSForEach", StringComparison.OrdinalIgnoreCase))
                    {
                        // We need to pass the empty enumerator to the ForEach operator, so that it can return an empty collection.
                        // The ForEach operator will not be able to call the script block if the enumerator is empty.
                    {
                        return InvokeForEachOnCollection(emptyEnumerator, args, argRestrictions).WriteToDebugLog(this);
                    }
                }

                return target.ThrowRuntimeError(args, BindingRestrictions.Empty, "InvokeMethodOnNull", ParserStrings.InvokeMethodOnNull).WriteToDebugLog(this);
            }

            PSMemberInfo memberInfo;
            if (_getMemberBinder.HasInstanceMember && PSGetMemberBinder.TryGetInstanceMember(target.Value, Name, out memberInfo))
            {
                // If there is an instance member, we generate (roughly) the following:
                //     PSMethodInfo methodInfo;
                //     if (PSInvokeMemberBinder.TryGetInstanceMethod(target.Value, Name, out methodInfoInfo))
                //         return methodInfo.Invoke(target, args);
                //     else

Review comment (suggestion):
```suggestion
                    if (string.Equals(Name, "Where", StringComparison.OrdinalIgnoreCase)
                        || string.Equals(Name, "PSWhere", StringComparison.OrdinalIgnoreCase))
```

Code after:
                args.Any(static mo => mo.Value is PSObject && (PSObject.Base(mo.Value) != mo.Value)))
            {
                object baseObject = PSObject.Base(target.Value);
                if (baseObject != null && Marshal.IsComObject(baseObject))
                {
                    // We unwrap only if the 'base' of 'target' is a COM object. It's unnecessary to unwrap in other cases,
                    // especially in the case that 'target' is a string, we would lose instance members on the PSObject.
                    // Therefore, we need to use a stricter restriction to make sure other type of PSObject 'target'
                    // doesn't get unwrapped.
                    return this.DeferForPSObject(args.Prepend(target).ToArray(), targetIsComObject: true).WriteToDebugLog(this);
                }
            }

            // Check if this is a COM Object
            DynamicMetaObject result;
            if (ComInterop.ComBinder.TryBindInvokeMember(this, _propertySetter, target, args, out result))
            {
                return result.UpdateComRestrictionsForPsObject(args).WriteToDebugLog(this);
            }

            var targetValue = PSObject.Base(target.Value);
            if (targetValue == null)
            {
                if (!_static && !_nonEnumerating)
                {
                    // As discussed with Bruce, the Where/ForEach operators should work on $null and return an empty collection.
                    // e.g. $null.Where{"I didn't run"} should return an empty collection
                    DynamicMetaObject emptyEnumerator = new DynamicMetaObject(
                        Expression.Call(Expression.NewArrayInit(typeof(object)), CachedReflectionInfo.IEnumerable_GetEnumerator),
                        BindingRestrictions.GetInstanceRestriction(Expression.Call(CachedReflectionInfo.PSObject_Base, target.Expression), null))
                        .WriteToDebugLog(this);
                    BindingRestrictions argRestrictions = args.Aggregate(BindingRestrictions.Empty, static (current, arg) => current.Merge(arg.PSGetMethodArgumentRestriction()));

                    // We need to pass the empty enumerator to the ForEach/Where operators, so that they can return an empty collection.
                    // The ForEach/Where operators will not be able to call the script block if the enumerator is empty.
                    if (s_whereSearchValues.Contains(Name))
                    {
                        return InvokeWhereOnCollection(emptyEnumerator, args, argRestrictions).WriteToDebugLog(this);
                    }

                    if (s_foreachSearchValues.Contains(Name))
                    {
                        return InvokeForEachOnCollection(emptyEnumerator, args, argRestrictions).WriteToDebugLog(this);
                    }
                }

                return target.ThrowRuntimeError(args, BindingRestrictions.Empty, "InvokeMethodOnNull", ParserStrings.InvokeMethodOnNull).WriteToDebugLog(this);
            }

            PSMemberInfo memberInfo;
            if (_getMemberBinder.HasInstanceMember && PSGetMemberBinder.TryGetInstanceMember(target.Value, Name, out memberInfo))