I'd like a general solution but as an example, assume i have an IEnumerable<string>
, where some can be parsed as integers, and some cannot.
var strings = new string[] { "1", "2", "notint", "3" };
Obviously if i did Select(s => int.Parse(s, temp))
it'd throw an exception when enumerated.
In this case i could do .All(s => int.TryParse(s, out temp))
first, however i want a general solution where i don't have to enumerate the IEnumerable
twice.
Ideally i'd like to be able to do the following, which calls my magic exception skipping method:
// e.g. parsing strings
var strings = new string[] { "1", "2", "notint", "3" };
var numbers = strings.Select(s => int.Parse(s)).SkipExceptions();
// e.g. encountering null object
var objects = new object[] { new object(), new object(), null, new object() }
var objecttostrings = objects.Select(o => o.ToString()).SkipExceptions();
// e.g. calling a method that could throw
var myClassInstances = new MyClass[] { new MyClass(), new MyClass(CauseMethodToThrow:true) };
var myClassResultOfMethod = myClassInstances.Select(mci => mci.MethodThatCouldThrow()).SkipExceptions();
How can i write the SkipExceptions()
extension method?
Some great answers for a SelectSkipExceptions()
method, however i wonder if a SkipExceptions()
method could be created, along the same lines as AsParallel()
.
Here's a small complete program to demonstrate an answer inspired by the maybe monad. You might want to change the name of the 'Maybe' class, as it is inspired by rather than actually being a 'Maybe' as defined in other languages.
Edit: depending on the needs of your code, you might also want
nothing
set totrue
if the result ofmap(input)
is null.You could just chain the Where and Select method together.
The use of the Where method effectively removes the need for you to write your own SkipExceptions method, because this is basically what you are doing.
This is the same answer as Thomas's, but with a lambda & LINQ expression. +1 for Thomas.
Create a
TryParseInt
method that returns aNullable<int>
:And use it in your query like that:
See also this article by Bill Wagner, which presents a very similar case.
Now, i don't think you can write something like a generic
SkipExceptions
method, because you would catch the exception too late, and it would end theSelect
loop... But you could probably write aSelectSkipException
method:Even the accepted answer may not be "general" enough. What if some day you find that you need to know what exceptions occurred?
The following extension
will help. Now you can add
SkipExceptions
:By using different
onException
callback, you can do different thingse => false
e => true
How about this (you might want to give this special Select Extension a better name)
Edit5 Added a using statement, thanks for the suggestion in comments
However this relies on the incoming IEnumerable not already being created (and therefore already having thrown Exceptions) as a list by the preceding Function. E.g. this would probably not work if you call it like this: Select(..).ToList().SkipExceptions()