@@ -821,22 +821,24 @@ private void CreateAggregateCore<TAccumulate, TResult>(
821821delegate_function_aggregate_step ? func_step = null ;
822822if ( func != null )
823823{
824- func_step = ( ctx , user_data , args ) =>
824+ func_step = static ( ctx , user_data , args ) =>
825825{
826- var context = ( AggregateContext < TAccumulate > ) user_data ;
826+ var definition = ( AggregateDefinition < TAccumulate , TResult > ) user_data ;
827+ ctx . state ??= new AggregateContext < TAccumulate > ( definition . Seed ) ;
828+
829+ var context = ( AggregateContext < TAccumulate > ) ctx . state ;
827830if ( context . Exception != null )
828831{
829832return ;
830833}
831834
832835// TODO: Avoid allocation when niladic
833- var reader = new SqliteParameterReader ( name , args ) ;
836+ var reader = new SqliteParameterReader ( definition . Name , args ) ;
834837
835838try
836839{
837- // TODO: Avoid closure by passing func via user_data
838840// NB: No need to set ctx.state since we just mutate the instance
839- context . Accumulate = func ( context . Accumulate , reader ) ;
841+ context . Accumulate = definition . Func ! ( context . Accumulate , reader ) ;
840842}
841843catch ( Exception ex )
842844{
@@ -848,16 +850,18 @@ private void CreateAggregateCore<TAccumulate, TResult>(
848850delegate_function_aggregate_final ? func_final = null ;
849851if ( resultSelector != null )
850852{
851- func_final = ( ctx , user_data ) =>
853+ func_final = static ( ctx , user_data ) =>
852854{
853- var context = ( AggregateContext < TAccumulate > ) user_data ;
855+ var definition = ( AggregateDefinition < TAccumulate , TResult > ) user_data ;
856+ ctx . state ??= new AggregateContext < TAccumulate > ( definition . Seed ) ;
857+
858+ var context = ( AggregateContext < TAccumulate > ) ctx . state ;
854859
855860if ( context . Exception == null )
856861{
857862try
858863{
859- // TODO: Avoid closure by passing resultSelector via user_data
860- var result = resultSelector ( context . Accumulate ) ;
864+ var result = definition . ResultSelector ! ( context . Accumulate ) ;
861865
862866new SqliteResultBinder ( ctx , result ) . Bind ( ) ;
863867}
@@ -881,7 +885,7 @@ private void CreateAggregateCore<TAccumulate, TResult>(
881885}
882886
883887var flags = isDeterministic ? SQLITE_DETERMINISTIC : 0 ;
884- var state = new AggregateContext < TAccumulate > ( seed ) ;
888+ var state = new AggregateDefinition < TAccumulate , TResult > ( name , seed , func , resultSelector ) ;
885889
886890if ( State == ConnectionState . Open )
887891{
@@ -915,6 +919,22 @@ private void CreateAggregateCore<TAccumulate, TResult>(
915919return values ;
916920}
917921
922+ private sealed class AggregateDefinition < TAccumulate , TResult >
923+ {
924+ public AggregateDefinition ( string name , TAccumulate seed , Func < TAccumulate , SqliteValueReader , TAccumulate > ? func , Func < TAccumulate , TResult > ? resultSelector )
925+ {
926+ Name = name ;
927+ Seed = seed ;
928+ Func = func ;
929+ ResultSelector = resultSelector ;
930+ }
931+
932+ public string Name { get ; }
933+ public TAccumulate Seed { get ; }
934+ public Func < TAccumulate , SqliteValueReader , TAccumulate > ? Func { get ; }
935+ public Func < TAccumulate , TResult > ? ResultSelector { get ; }
936+ }
937+
918938private sealed class AggregateContext < T >
919939{
920940public AggregateContext ( T seed )