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