Reputation:
If I have the following working code:
List<MyClass> results = new List<MyClass>();
for(int i = 0; i < source.Count; i++)
try{ results.Add(Fetch(source[i])); }
catch(Exception ex){ results.Add(new MyClass("poof!")); }
...
public MyClass Fetch(Object source){ ... }
and would like to remake it into LINQ, how can I manage the try-catch? If I put it around the following expression, It's not going to poof me. My suggestion would be to migrate catching into the method but I'm not sure how optimal/recommended that is. Can one tell at all or is depending on specifics of the scenario?
IEnumerable<String> strings = source.Select(e => Fetch(e));
public MyClass Fetch(Object source){ try{ ... } catch(){ ... } }
It'd be cool with something like this pseudo-code. I'm thinking the method .First()
and it's more-potent brother .FirstOrDefault()
, but with additional capacity.
IEnumerable<String> strings = source.Select(e => Fetch(e)).Excepted(...);
Am I way off?
Upvotes: 1
Views: 112
Reputation: 25563
You'd get the same behaviour as your original code from
List<String> results = source.Select(e => { try
{
return Fetch(e);
}
catch(Exception)
{
return MyClass("poof");
}
}).ToList();
But I think you should reconsider using try/catch this way. It has a severe performance cost, and is not intended to handle non-exceptional cases. Better check first if e
is fetchable and do something like
List<String> results = source.Where(e => IsFetchable(e))
.Select(e => Fetch(e))
.ToList();
Upvotes: 0
Reputation: 754813
Your best bet is to move the try / catch
block into a separate method and use that method as the selector.
public MyClass FetchOrDefault(object source){
try {
return Fetch(source);
} catch (Exception ex) {
return new MyClass("poof");
}
}
// Method call syntax
var e = source.Select(x => x.FetchOrDefault(x));
// LINQ syntax
var e = from x in source select FetchOrDefault(x);
Upvotes: 2
Reputation: 203833
I don't think you'll be able to create your Excepted
class, but you can create a Select
method with two selectors, one for the error case:
public static IEnumerable<TResult> Select<TSource, TResult>(this IEnumerable<TSource> source,
Func<TSource, TResult> selector, Func<TSource, TResult> secondarySelector)
{
foreach (var item in source)
{
TResult nextValue;
try
{
nextValue = selector(item);
}
catch
{
nextValue = secondarySelector(item);
}
yield return nextValue;
}
}
Then it would allow you to do:
var results = source.Select(item => Fetch(item)
, item => new MyClass("poof!"))
.ToList();
Your secondary selector could also take the exception as a parameter, if that would be appropriate.
Upvotes: 0
Reputation: 16065
The easiest solution is to just do what you did already i.e. you can include code block.
IEnumerable<String> strings = source.Select(e =>
{
try
{
return Fetch(e);
}
catch
{
return new MyClass("poof");
}
}
);
Upvotes: 0