Repository: dotnet/runtime
File: src/libraries/System.Private.CoreLib/src/System/Array.cs (C#)

Code before:
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }

            for (int i = 0; i < array.Length; i++)
            {
                if (match(array[i]))
                {
                    return array[i];
                }
            }
            return default;
        }

        public static T[] FindAll<T>(T[] array, Predicate<T> match)
        {
            if (array == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
            }

            if (match == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }

            List<T>? heapMatches = null; // only allocate if needed
            InlineArray16<T> stackAllocatedMatches = default;
            const int InlineArrayLength = 16;
            int stackAllocatedMatchesFound = 0;
            for (int i = 0; i < array.Length; i++)
            {
                if (match(array[i]))
                {
                    if (stackAllocatedMatchesFound < InlineArrayLength)
                    {
                        stackAllocatedMatches[stackAllocatedMatchesFound++] = array[i];
                    }
                    else
                    {
                        // Revert to the old logic, allocating and growing a List
                        heapMatches ??= [];
                        heapMatches.Add(array[i]);
                    }
                }
            }

            if (stackAllocatedMatchesFound == 0)
            {
                return EmptyArray<T>.Value;
            }


Review comment (performance):
it is possible to extract the verbose code into a struct collection. I mean code like this:
```c#
    public static T[] FindAll<T>(T[] array, Predicate<T> match)
    {
        if (array == null)
        {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
        }

        if (match == null)
        {
            ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
        }

        OptimizedArrayBuilder<T> arrayBuilder = new OptimizedArrayBuilder<T>();
        for (int i = 0; i < array.Length; i++)
        {
            if (match(array[i]))
            {
                arrayBuilder.Add(array[i]);
            }
        }

        if (arrayBuilder.Count == 0)
        {
            return [];
        }

        return arrayBuilder.Build();
    }

    private ref struct OptimizedArrayBuilder<T>
    {
        const int InlineArrayLength = 16;
        private List<T>? heapMatches;
        private InlineArray16<T> stackAllocatedMatches;
        private int stackAllocatedMatchesFound;

        public SmallArrayBuilder()
        {
            this.heapMatches = null; // only allocate if needed
            this.stackAllocatedMatches = default;
            this.stackAllocatedMatchesFound = 0;
        }

        public readonly int Count => this.stackAllocatedMatchesFound + (heapMatches?.Count ?? 0);

        public void Add(T item)
        {
            if (stackAllocatedMatchesFound < InlineArrayLength)
            {
                stackAllocatedMatches[stackAllocatedMatchesFound++] = item;
            }
            else
            {
                // Revert to the old logic, allocating and growing a List
                heapMatches ??= [];
                heapMatches.Add(item);
            }
        }

        public readonly T[] Build()
        {
            T[] result = new T[this.Count];

            int index = 0;
            foreach (T stackAllocatedMatch in stackAllocatedMatches)
            {
                result[index++] = stackAllocatedMatch;
                if (index >= stackAllocatedMatchesFound)
                {
                    break;
                }
            }

            heapMatches?.CopyTo(result.AsSpan(start: InlineArrayLength));

            return result;
        }
    }
```

Code after:
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
            }

            if (match == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }

            for (int i = 0; i < array.Length; i++)
            {
                if (match(array[i]))
                {
                    return array[i];
                }
            }
            return default;
        }

        public static T[] FindAll<T>(T[] array, Predicate<T> match)
        {
            if (array == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.array);
            }

            if (match == null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.match);
            }

            InlineArray4<T> stackAllocatedMatches = default;
            Span<T> span = stackAllocatedMatches;
            int foundCount = 0;
            T[]? values = null;

            foreach (T value in array)
            {
                if (match(value))
                {
                    if (foundCount >= span.Length)
                    {
                        values = new T[Math.Min((uint)span.Length * 2, (uint)array.Length)];
                        span.CopyTo(values);
                        span = values;
                    }

                    span[foundCount++] = value;
                }
            }

            return values?.Length == foundCount ? values : span[..foundCount].ToArray();