Repository: dotnet/runtime
File: src/libraries/Microsoft.Extensions.DependencyInjection/src/ServiceLookup/ServiceProviderEngineScope.cs (C#)

Code before:
                            return Await(i, vt, toDispose);
                        }

                        // If its a IValueTaskSource backed ValueTask,
                        // inform it its result has been read so it can reset
                        vt.GetAwaiter().GetResult();
                    }
                    else
                    {
                        ((IDisposable)disposable).Dispose();
                    }
                }
                catch (Exception ex)
                {
                    exceptions ??= new List<Exception>();
                    exceptions.Add(ex);
                }
            }

            if (exceptions is null)
            {
                return default;
            }

            var exception = exceptions.Count == 1 ? exceptions[0] : new AggregateException(exceptions);
            return new ValueTask(Task.FromException(exception));

            static async ValueTask Await(int i, ValueTask vt, List<object> toDispose)
            {
                await vt.ConfigureAwait(false);
                // vt is acting on the disposable at index i,
                // decrement it and move to the next iteration
                i--;

                for (; i >= 0; i--)
                {
                    object disposable = toDispose[i];
                    if (disposable is IAsyncDisposable asyncDisposable)
                    {
                        await asyncDisposable.DisposeAsync().ConfigureAwait(false);
                    }
                    else
                    {
                        ((IDisposable)disposable).Dispose();
                    }
                }
            }
        }

        private List<object>? BeginDispose()
        {

Review comment (bug):
With the new per-item try/catch and aggregation, `DisposeAsync` still short-circuits and does not aggregate exceptions for *asynchronously* completing disposals: when `DisposeAsync` returns a `ValueTask` that is not yet completed, the method returns immediately via `Await(i, vt, toDispose)`, so any exception thrown from `vt` (or from later disposables in `Await`) is propagated as a single exception and disposal of remaining items stops early. If the intent is to apply the new "dispose all and aggregate exceptions" behavior consistently, the async path needs to either (1) aggregate exceptions inside `Await` while still disposing all remaining items, or (2) propagate information back so that `DisposeAsync` can aggregate exceptions from the awaited portion instead of returning the first failure only.

Code after:
                        vt.GetAwaiter().GetResult();
                    }
                    else
                    {
                        ((IDisposable)disposable).Dispose();
                    }
                }
                catch (Exception exception)
                {
                    AddExceptionToCache(ref exceptionsCache, exception);
                }
            }

            CheckExceptionCache(exceptionsCache);

            return default;

            static async ValueTask Await(int i, ValueTask vt, List<object> toDispose, object? exceptionsCache)
            {
                try
                {
                    await vt.ConfigureAwait(false);
                }
                catch (Exception exception)
                {
                    AddExceptionToCache(ref exceptionsCache, exception);
                }

                // vt is acting on the disposable at index i,
                // decrement it and move to the next iteration
                i--;

                for (; i >= 0; i--)
                {
                    try
                    {
                        object disposable = toDispose[i];
                        if (disposable is IAsyncDisposable asyncDisposable)
                        {
                            await asyncDisposable.DisposeAsync().ConfigureAwait(false);
                        }
                        else
                        {
                            ((IDisposable)disposable).Dispose();
                        }
                    }
                    catch (Exception exception)
                    {
                        AddExceptionToCache(ref exceptionsCache, exception);
                    }
                }