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

Code before:
                foreach (PSSetMemberBinder binder in s_binderCache.Values)
                {
                    binder._getMemberBinder._version += 1;
                }
            }
        }
    }

    internal class PSInvokeBinder : InvokeBinder
    {
        internal PSInvokeBinder(CallInfo callInfo) : base(callInfo)
        {
        }

        public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
        {
            return errorSuggestion ?? target.ThrowRuntimeError(args, BindingRestrictions.Empty, "CannotInvoke", ParserStrings.CannotInvoke);
        }
    }

    internal sealed class PSInvokeMemberBinder : InvokeMemberBinder
    {
        private const string WhereMagicMethodName = "Where";
        private const string WhereMagicMethodPSName = $"PS{WhereMagicMethodName}";
        private const string ForeachMagicMethodName = "Foreach";
        private const string ForeachMagicMethodPSName = $"PS{ForeachMagicMethodName}";

        private static readonly SearchValues<string> s_whereSearchValues = SearchValues.Create([WhereMagicMethodName, WhereMagicMethodPSName], StringComparison.OrdinalIgnoreCase);   
        private static readonly SearchValues<string> s_foreachSearchValues = SearchValues.Create([ForeachMagicMethodName, ForeachMagicMethodPSName], StringComparison.OrdinalIgnoreCase);

        internal enum MethodInvocationType
        {
            Ordinary,
            Setter,
            Getter,
            BaseCtor,
            NonVirtual,
        }

        private sealed class KeyComparer : IEqualityComparer<PSInvokeMemberBinderKeyType>
        {
            public bool Equals(PSInvokeMemberBinderKeyType x, PSInvokeMemberBinderKeyType y)
            {
                return x.Item1.Equals(y.Item1, StringComparison.OrdinalIgnoreCase)
                       && x.Item2.Equals(y.Item2)
                       && x.Item3 == y.Item3
                       && x.Item4 == y.Item4
                       && ((x.Item5 == null) ? (y.Item5 == null) : x.Item5.Equals(y.Item5))
                       && x.Item6 == y.Item6
                       && x.Item7 == y.Item7;
            }

Review comment (suggestion):
Those are only used in the declaration of `s_whereSearchValues` and `s_foreachSearchValues` below, so it doesn't seem to be needed to have them as constant variables.

Code after:
                foreach (PSSetMemberBinder binder in s_binderCache.Values)
                {
                    binder._getMemberBinder._version += 1;
                }
            }
        }
    }

    internal class PSInvokeBinder : InvokeBinder
    {
        internal PSInvokeBinder(CallInfo callInfo) : base(callInfo)
        {
        }

        public override DynamicMetaObject FallbackInvoke(DynamicMetaObject target, DynamicMetaObject[] args, DynamicMetaObject errorSuggestion)
        {
            return errorSuggestion ?? target.ThrowRuntimeError(args, BindingRestrictions.Empty, "CannotInvoke", ParserStrings.CannotInvoke);
        }
    }

    internal sealed class PSInvokeMemberBinder : InvokeMemberBinder
    {
        private static readonly SearchValues<string> s_whereSearchValues = SearchValues.Create(
            ["Where", "PSWhere"],
            StringComparison.OrdinalIgnoreCase);

        private static readonly SearchValues<string> s_foreachSearchValues = SearchValues.Create(
            ["ForEach", "PSForEach"],
            StringComparison.OrdinalIgnoreCase);

        internal enum MethodInvocationType
        {
            Ordinary,
            Setter,
            Getter,
            BaseCtor,
            NonVirtual,
        }

        private sealed class KeyComparer : IEqualityComparer<PSInvokeMemberBinderKeyType>
        {
            public bool Equals(PSInvokeMemberBinderKeyType x, PSInvokeMemberBinderKeyType y)
            {
                return x.Item1.Equals(y.Item1, StringComparison.OrdinalIgnoreCase)
                       && x.Item2.Equals(y.Item2)
                       && x.Item3 == y.Item3
                       && x.Item4 == y.Item4
                       && ((x.Item5 == null) ? (y.Item5 == null) : x.Item5.Equals(y.Item5))
                       && x.Item6 == y.Item6
                       && x.Item7 == y.Item7;
            }