#nullable enable using System; using System.Collections; using System.Collections.Generic; using System.Collections.Immutable; using System.Runtime.CompilerServices; namespace io; /// /// An immutable list implementation that tracks history, metadata, and time. /// public record class List : io.Timed>, IImmutableList { static public List Empty { get; } = new(); public ImmutableList Values { get; init; } = ImmutableList.Empty; public List() { } // Required for 'with' expressions to work with the base class hierarchy protected List( io.Timed> original ) : base( original ) { } // Helper to apply changes using the Process method private List Change( Func, ImmutableList> listChange, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1, [CallerArgumentExpression( "listChange" )] string reason = "" ) { var newValues = listChange( Values ); return ReferenceEquals( Values, newValues ) ? this : Process( l => l with { Values = newValues }, reason, dbgMethod, dbgPath, dbgLine, reason ); } // --- IImmutableList implementation using the Change helper --- public T this[int index] => Values[index]; public int Count => Values.Count; public List Add( T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Add( value ), dbgMethod, dbgPath, dbgLine ); public List AddRange( IEnumerable items, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.AddRange( items ), dbgMethod, dbgPath, dbgLine ); public List Clear( [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Clear(), dbgMethod, dbgPath, dbgLine ); #region IImmutableList Implementati, dbgMethod, dbgPath, dbgLineon public List Insert( int index, T element, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Insert( index, element ), dbgMethod, dbgPath, dbgLine ); public List InsertRange( int index, IEnumerable items, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.InsertRange( index, items ), dbgMethod, dbgPath, dbgLine ); public List Remove( T value, IEqualityComparer? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Remove( value, equalityComparer ), dbgMethod, dbgPath, dbgLine ); public List Remove( T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Remove( value, EqualityComparer.Default, dbgMethod, dbgPath, dbgLine ); public List RemoveAll( Predicate match, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveAll( match ), dbgMethod, dbgPath, dbgLine ); public List RemoveAt( int index, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveAt( index ), dbgMethod, dbgPath, dbgLine ); public List RemoveRange( int index, int count, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveRange( index, count ), dbgMethod, dbgPath, dbgLine ); public List RemoveRange( IEnumerable items, IEqualityComparer? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.RemoveRange( items, equalityComparer ), dbgMethod, dbgPath, dbgLine ); public List Replace( T oldValue, T newValue, IEqualityComparer? equalityComparer, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.Replace( oldValue, newValue, equalityComparer ), dbgMethod, dbgPath, dbgLine ); public List SetItem( int index, T value, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => Change( v => v.SetItem( index, value ), dbgMethod, dbgPath, dbgLine ); public int IndexOf( T item, int index, int count, IEqualityComparer? equalityComparer ) => Values.IndexOf( item, index, count, equalityComparer ?? EqualityComparer.Default ); public int LastIndexOf( T item, int index, int count, IEqualityComparer? equalityComparer ) => Values.LastIndexOf( item, index, count, equalityComparer ?? EqualityComparer.Default ); public int IndexOf( T item, [CallerMemberName] string dbgMethod = "", [CallerFilePath] string dbgPath = "", [CallerLineNumber] int dbgLine = -1 ) => IndexOf( item, 0, Count, EqualityComparer.Default ); IImmutableList IImmutableList.Clear() => Clear(); IImmutableList IImmutableList.Add( T value ) => Add( value ); IImmutableList IImmutableList.AddRange( IEnumerable items ) => AddRange( items ); IImmutableList IImmutableList.Insert( int index, T element ) => Insert( index, element ); IImmutableList IImmutableList.InsertRange( int index, IEnumerable items ) => InsertRange( index, items ); IImmutableList IImmutableList.Remove( T value, IEqualityComparer? equalityComparer ) => Remove( value, equalityComparer ); IImmutableList IImmutableList.RemoveAll( Predicate match ) => RemoveAll( match ); IImmutableList IImmutableList.RemoveAt( int index ) => RemoveAt( index ); IImmutableList IImmutableList.RemoveRange( IEnumerable items, IEqualityComparer? equalityComparer ) => RemoveRange( items, equalityComparer ); IImmutableList IImmutableList.RemoveRange( int index, int count ) => RemoveRange( index, count ); IImmutableList IImmutableList.Replace( T oldValue, T newValue, IEqualityComparer? equalityComparer ) => Replace( oldValue, newValue, equalityComparer ); IImmutableList IImmutableList.SetItem( int index, T value ) => SetItem( index, value ); #endregion // --- Standard Interfaces --- public IEnumerator GetEnumerator() => Values.GetEnumerator(); IEnumerator IEnumerable.GetEnumerator() => ( (IEnumerable)Values ).GetEnumerator(); }