File: Evaluation\ItemDataCollectionValue.cs
Web Access
Project: ..\..\..\src\Build\Microsoft.Build.csproj (Microsoft.Build)
// 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.Generic;
 
#nullable disable
 
namespace Microsoft.Build.Evaluation
{
    /// <summary>
    /// An efficient multi-value wrapper holding one or more items.
    /// </summary>
    internal struct ItemDataCollectionValue<I>
    {
        /// <summary>
        /// A non-allocating enumerator for the multi-value.
        /// </summary>
        public struct Enumerator : IEnumerator<I>
        {
            private object _value;
            private int _index;
 
            public Enumerator(object value)
            {
                _value = value;
                _index = -1;
            }
 
            public I Current => (_value is IList<I> list) ? list[_index] : (I)_value;
            object System.Collections.IEnumerator.Current => Current;
 
            public void Dispose()
            { }
 
            public bool MoveNext()
            {
                // If value is not a list, it is either null or a single item.
                int count = (_value is IList<I> list) ? list.Count : (_value is null ? 0 : 1);
                if (_index + 1 < count)
                {
                    _index++;
                    return true;
                }
                return false;
            }
 
            public void Reset()
            {
                _index = -1;
            }
        }
 
        /// <summary>
        /// Holds one value or a list of values.
        /// </summary>
        private object _value;
 
        public bool IsEmpty => _value == null || (_value is List<I> list && list.Count == 0);
 
        public ItemDataCollectionValue(I item)
        {
            _value = item;
        }
 
        public void Add(I item)
        {
            if (_value is null)
            {
                _value = item;
            }
            else
            {
                if (_value is not List<I> list)
                {
                    list = new List<I>()
                    {
                        (I)_value
                    };
                    _value = list;
                }
                list.Add(item);
            }
        }
 
        public void Delete(I item)
        {
            if (_value is List<I> list)
            {
                list.Remove(item);
            }
            else if (object.Equals(_value, item))
            {
                _value = null;
            }
        }
 
        public void Replace(I oldItem, I newItem)
        {
            if (_value is List<I> list)
            {
                int index = list.IndexOf(oldItem);
                if (index >= 0)
                {
                    list[index] = newItem;
                }
            }
            else if (object.Equals(_value, oldItem))
            {
                _value = newItem;
            }
        }
 
        public Enumerator GetEnumerator()
        {
            return new Enumerator(_value);
        }
    }
}