File: System\Linq\DebugView.cs
Web Access
Project: src\src\libraries\System.Linq\src\System.Linq.csproj (System.Linq)
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
 
using System.Collections;
using System.Collections.Generic;
using System.Diagnostics;
 
namespace System.Linq
{
    // NOTE: DO NOT DELETE THE FOLLOWING DEBUG VIEW TYPES.
    // Although it might be tempting due to them not be referenced anywhere in this library,
    // Visual Studio (and potentially other debuggers) currently depends on their existence to
    // enable the "Results" view in watch windows.  Specifically:
    // - It creates the debug view by name (the view then has the same requirements as other views).
    // - It looks for the empty exception by name.
    // - It uses the exception's Empty property by name.
 
    /// <summary>
    /// This class provides the items view for the Enumerable
    /// </summary>
    /// <typeparam name="T"></typeparam>
    internal sealed class SystemCore_EnumerableDebugView<T>
    {
        public SystemCore_EnumerableDebugView(IEnumerable<T> enumerable)
        {
            if (enumerable is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.enumerable);
            }
 
            _enumerable = enumerable;
        }
 
        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
        public T[] Items
        {
            get
            {
                T[] array = _enumerable.ToArray();
                if (array.Length == 0)
                {
                    throw new SystemCore_EnumerableDebugViewEmptyException();
                }
 
                return array;
            }
        }
 
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private readonly IEnumerable<T> _enumerable;
    }
 
    internal sealed class SystemCore_EnumerableDebugViewEmptyException : Exception
    {
#pragma warning disable CA1822
        // This property value is used by the debugger EE as the message
        // displayed when a dynamic object has no members.
        public string Empty => SR.EmptyEnumerable;
#pragma warning restore CA1822
    }
 
    internal sealed class SystemCore_EnumerableDebugView
    {
        public SystemCore_EnumerableDebugView(IEnumerable enumerable)
        {
            if (enumerable is null)
            {
                ThrowHelper.ThrowArgumentNullException(ExceptionArgument.enumerable);
            }
 
            _enumerable = enumerable;
        }
 
        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
        public object?[] Items
        {
            get
            {
                List<object?> tempList = [.. _enumerable];
 
                if (tempList.Count == 0)
                {
                    throw new SystemCore_EnumerableDebugViewEmptyException();
                }
 
                return tempList.ToArray();
            }
        }
 
        [DebuggerBrowsable(DebuggerBrowsableState.Never)]
        private readonly IEnumerable _enumerable;
    }
 
    internal sealed class SystemLinq_GroupingDebugView<TKey, TElement>
    {
        private readonly Grouping<TKey, TElement> _grouping;
        private TElement[]? _cachedValues;
 
        public SystemLinq_GroupingDebugView(Grouping<TKey, TElement> grouping)
        {
            _grouping = grouping;
        }
 
        public TKey Key => _grouping.Key;
 
        // The name of this property must alphabetically follow `Key` so the elements appear last in the display.
        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
        public TElement[] Values => _cachedValues ??= _grouping.ToArray();
    }
 
    internal sealed class SystemLinq_LookupDebugView<TKey, TElement>
    {
        private readonly ILookup<TKey, TElement> _lookup;
        private IGrouping<TKey, TElement>[]? _cachedGroupings;
 
        public SystemLinq_LookupDebugView(ILookup<TKey, TElement> lookup)
        {
            _lookup = lookup;
        }
 
        [DebuggerBrowsable(DebuggerBrowsableState.RootHidden)]
        public IGrouping<TKey, TElement>[] Groupings => _cachedGroupings ??= _lookup.ToArray();
    }
}