Stavolta è andata così. Mi trovavo spesso a scrivere codice non transazionale in cui devo fare un'operazione su una serie di oggetti ma le eccezioni dovevano essere gestite ed aggregate, in questo modo:
var erroriGestiti = new List<QualcheCosa>(); foreach( var item in items ) { try { FaiQualcosaCon(item); } catch( QualcheTipoDiEccezione excp) { a.Add( CreaQualcheCosaDa(excp) ); } } return erroriGestiti;

public static IEnumerable<TReturn> CollectErrors<TItem, TException, TReturn>( this IEnumerable<TItem> items, Action<TItem> act, Converter<TException, TReturn> exceptionHandler ) where TException : Exception { if (items == null) throw new ArgumentNullException("items"); if (act == null) throw new ArgumentNullException("act"); if (exceptionHandler == null) throw new ArgumentNullException("exceptionHandler"); return items .Aggregate(new List<TReturn>(), (collector, item) => { try { act(item); } catch (TException ex) { collector.Add(exceptionHandler(ex)); } return collector; }); } // e questo mi permette di scrivere: [TestMethod] public void TestMethod1() { var expected = new[] { "error", "error", "error" }; var actual = new[] { 1, 2, 3, 4, 5, 6 } .CollectErrors(i => { if (i > 3) throw new IndexOutOfRangeException(); }, (IndexOutOfRangeException e) => "error"); Assert.IsTrue(actual.SequenceEqual(expected)); }certo non è una sintassi molto chiara come potrebbe essere in Scala, ma non è poi tanto male, no?
Nessun commento:
Posta un commento