Remove an item from ienumerable<string> - c#

I have a method that expect IEnumerable<string> as you can see here :
public static string FromDecimalAscii(IEnumerable<string> input)
{
return new string(input.Select(s => (char)int.Parse(s)).ToArray());
}
But every time the last record of my IEnumerable is empty so i got an error in this line because of that :
return new string(input.Select(s => (char)int.Parse(s)).ToArray());
So i have to remove that item from my IEnumerable .
The error:Input string was not in a correct format
Any ideas will be appreciated.
Best regards

You need just to filter collection with Where:
return new string(input.Where(s => !string.IsNullOrEmpty(s))
.Select(s => (char)int.Parse(s)).ToArray());
You can also use extension method to use TryParse:
static class Extensions
{
public delegate bool TryParseDelegate<TSource>(string s, out TSource source);
public static IEnumerable<TResult> WhereParsed<TSource, TResult>(
this IEnumerable<TSource> source,
TryParseDelegate<TResult> tryParse)
{
// TODO: check arguments against null first
foreach (var item in source)
{
TResult result;
if (tryParse(item != null ? item.ToString() : null, out result))
{
yield return result;
}
}
}
}
Usage:
var collection = input.WhereParsed<string, int>(int.TryParse)
.Cast<char>()
.ToArray();
return new string(collection);

Related

Implement extension Method C#

I need to implement this method :Reflectable reflect<T>(IEnumerable<T> src)
but i'm having troubles to get the expected output.
Hope someone can help me thanks.
Here the interface Reflectable:
interface Reflectable : IEnumerable<string> { Reflectable Prop(string propName);}
and the expected Output:
IEnumerable<Student> stds = //Students
IEnumerable<String> r1 = reflect(stds).Prop("Id");
IEnumerable<String> r2 = reflect(stds).Prop("Name").Prop("Id").Prop("Age");
IEnumerable<String> r3 = reflect(stds);
r1.ToList().ForEach(Console.Write); // {3213}{3124}{35454}...
r2.ToList().ForEach(Console.Write); // {Jose, 3213, 89}{Maria, 3124, 34}{Prominencia, 35454, 23}...
r3.ToList().ForEach(Console.Write); // {}{}{}...
I still think this idea of yours should be murdered in its sleep, or before birth...
public class ReflectionHelper<T>
: IEnumerable<string>
{
private string[] _properties;
private IEnumerable<T> _list;
public ReflectionHelper(IEnumerable<T> list, string[] properties)
{
_properties = properties;
_list = list;
}
public ReflectionHelper<T> Prop(string property)
{
return new ReflectionHelper<T>(_list, _properties.Concat(new string[]{ property}).ToArray());
}
public ReflectionHelper<T> Prop(string property)
{
return new ReflectionHelper<T>(_list, _properties.Concat(new string[] { property }).ToArray());
}
public static implicit operator List<string>(ReflectionHelper<T> helper)
{
return helper._list.Select(item => string.Join(",",
(from p in helper._properties
select typeof(T).GetProperty(p).GetValue(item, null)).ToArray())).ToList();
}
public IEnumerator<string> GetEnumerator()
{
return _list.Select(item => string.Join(",",
(from p in _properties
select typeof (T).GetProperty(p).GetValue(item, null)).ToArray()))
.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator();
}
}
public static class ReflectionHelperExtension
{
public static ReflectionHelper<T> Prop<T>(this IEnumerable<T> items, string property)
{
return new ReflectionHelper<T>(items, new string[] { property });
}
}
If I understand what you're achieving, extension methods would be a way to do it, and here is how:
// This class has to be static for extension methods to be detected
public static class MyExtensions
{
// using "this" before the first parameter will make it an extension of the type
public static IEnumerable<string> Prop<T>(this IEnumerable<T> enumerable, string propName)
{
var type = typeof(T);
// Note that this can throw an exception if the property is not found
var info = type.GetProperty(propName);
// Here are your students, considering that <T> is <Student>
foreach (var item in enumerable)
{
// return the value fromt the item, I'm using ToString here for
// simplicity, but since you don't know the property type in
// advance, you can't really do anything else than assumne its
// type is plain "object"
yield return info.GetValue(item).ToString();
}
}
}
One thing you won't be able to do is to chain them like #lomed said, since it returns an IEnumerable.
public static class EnumerableReflect
{
private static string OneElementReflect<T>(T e, PropertyInfo[] props)
{
var values = props.Select(x => x.GetValue(e).ToString());
return "{" + string.Join(", ", values)) + "}";
}
public static IEnumerable<string> enumerbleString<T>(this IEnumerable<T> collection, params string[] PropertysNames)
{
var props = PropertysNames.Select(x => typeof(T).GetProperty(x)).ToArray();
return collection.Select(x => OneElementReflect(x, props));
}
}

Can I take either string or IEnumerable<T>, where T is string or IEnumerable<T>?

I have a utility method that processes a collection of strings, let's say:
public static string MyJoin(this IEnumerable<string> strings)
{
return string.Join(Environment.NewLine, strings);
}
I'd like to be able to also process IEnumerable<IEnumerable<string>> and IEnumerable<IEnumerable<IEnumerable<string>>> and so on, all of them in this way:
public static string MyJoin(this IEnumerable<IEnumerable<string>> strings)
{
return strings.Select(x => x.MyJoin()).MyJoin();
}
public static string MyJoin(this IEnumerable<IEnumerable<IEnumerable<string>>> strings)
{
return strings.Select(x => x.MyJoin()).MyJoin();
}
Is there any way I can elegantly express this without hardcoding all the possible levels I might want to use?
I've tried to do it with generics, but I just can't figure out the right constraints (if there are any).
I'd also like to avoid declaring a new type, if at all possible.
Performance, on the other hand, is not critical.
Based on Stefan's solution, simplified and compilation-fixed version
public static string MyJoin(this IEnumerable items)
{
if (items is IEnumerable<string>)
{
return string.Join(Environment.NewLine, (IEnumerable<string>)items);
}
if (items is IEnumerable<IEnumerable>)
{
return items.Cast<IEnumerable>().Select(x => x.MyJoin())).MyJoin();
}
throw new InvalidOperationException("Type is not a (nested) enumarable of strings");
}
Be careful with IEnumerable<T> and strings, because a string is an IEnumerable<T>, where T is char.
Static implementation using multiple overloads:
public static string MyJoin(this IEnumerable<IEnumerable<IEnumerable<string>>> items)
{
return items.SelectMany(x => x).MyJoin();
}
public static string MyJoin(this IEnumerable<IEnumerable<string>> items)
{
return items.SelectMany(x => x).MyJoin();
}
public static string MyJoin(this IEnumerable<string> strings)
{
return string.Join(Environment.NewLine, strings);
}
You cannot have a single generic method and "unwrap" the generic argument dynamically.
Implementation using reflection:
public static string MyJoin<T>(this IEnumerable<T> items)
{
if (typeof(T) == typeof(string)
{
return items.Cast<string>().MyStringJoin();
}
var innerIEnumerableType = typeof(T).GetInterfaces().FirstOrDefault(x => x.IsGeneric()
&& x.GetGenericType() == typeof(IEnumerable<>);
if (innerIEnumerableType != null)
{
// create generic method to
var method = typeof(ThisType).GetMethod("MyJoin", /* some flags */)
.MakeGenericMethod(innerIEnumerableType.GetGenericArguments().First())
// recursive call to generic method
return items.Select(x => (string)method.Invoke(null, x)).MyStringJoin();
}
throw new InvalidOperationException("Type is not a (nested) enumarable of strings")
}
public static string MyStringJoin(this IEnumerable<string> strings)
{
return string.Join(Environment.NewLine, strings);
}
To be honest, reflection isn't useful here. Why use generics, if it isn't typesafe anyway? At the end you could just as well use non-generic IEnumerable. It's much easier to implement. See Denis Itskovich's solution, he managed to write down what I actually tried to do.
Rather than having an IEnumerable of an unknown type, what you're really trying to do here is create a tree based structure. The most effective way of doing this is to create a Node class that can represent a value an its children.
public class Node
{
public Node(string value)
{
Value = value;
Children = Enumerable.Empty<Node>();
}
public Node(string value, IEnumerable<Node> children)
{
Value = value;
Children = children;
}
public string Value { get; private set; }
public IEnumerable<Node> Children { get; private set; }
}
This is now a much easier structure to traverse. Here is a general purpose tree traversal method which we can apply to this case:
public static IEnumerable<T> Traverse<T>(T item,
Func<T, IEnumerable<T>> childSelector)
{
var stack = new Stack<T>();
stack.Push(item);
while (stack.Any())
{
var next = stack.Pop();
yield return next;
foreach (var child in childSelector(next))
stack.Push(child);
}
}
var allValues = Traverse(rootNode, node => node.Children)
.Select(node => node.Value);
Partly inspired by Stefan's answer, I've reached a working solution that compiles without generics and (unfortunately) with mostly runtime type checking:
public static string MyJoin(this IEnumerable<string> strings)
{
return string.MyJoin(Environment.NewLine, strings);
}
public static string MyJoin(this IEnumerable<object> items)
{
if (items.All(x => x is string))
return items.Cast<string>().MyJoin();
if (items.All(x => x is IEnumerable<object>))
return items.Cast<IEnumerable<object>>().Select(x => x.MyJoin()).MyJoin();
throw new InvalidOperationException("The argument was not a nested enumerable of strings.");
}
Use the SelectMany extension method.

LINQ query to perform a projection, skipping or wrapping exceptions where source throws on IEnumerable.GetNext()

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().
How about this (you might want to give this special Select Extension a better name)
public static IEnumerable<TOutput> SelectIgnoringExceptions<TInput, TOutput>(
this IEnumerable<TInput> values, Func<TInput, TOutput> selector)
{
foreach (var item in values)
{
TOutput output = default(TOutput);
try
{
output = selector(item);
}
catch
{
continue;
}
yield return output;
}
}
Edit5
Added a using statement, thanks for the suggestion in comments
public static IEnumerable<T> SkipExceptions<T>(
this IEnumerable<T> values)
{
using(var enumerator = values.GetEnumerator())
{
bool next = true;
while (next)
{
try
{
next = enumerator.MoveNext();
}
catch
{
continue;
}
if(next) yield return enumerator.Current;
}
}
}
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()
Create a TryParseInt method that returns a Nullable<int>:
int? TryParseInt(string s)
{
int i;
if (int.TryParse(s, out i))
return i;
return null;
}
And use it in your query like that:
var numbers = strings.Select(s => TryParseInt(s))
.Where(i => i.HasValue)
.Select(i => i.Value);
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 the Select loop... But you could probably write a SelectSkipException method:
public static IEnumerable<TResult> SelectSkipExceptions<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
{
if (source == null)
throw new ArgumentNullException("source");
if (selector == null)
throw new ArgumentNullException("selector");
return source.SelectSkipExceptionsIterator(selector);
}
private static IEnumerable<TResult> SelectSkipExceptionsIterator<TSource, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TResult> selector)
{
foreach(var item in source)
{
TResult value = default(TResult);
try
{
value = selector(item);
}
catch
{
continue;
}
yield return value;
}
}
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
static class EnumeratorHelper {
//Don't forget that GetEnumerator() call can throw exceptions as well.
//Since it is not easy to wrap this within a using + try catch block with yield,
//I have to create a helper function for the using block.
private static IEnumerable<T> RunEnumerator<T>(Func<IEnumerator<T>> generator,
Func<Exception, bool> onException)
{
using (var enumerator = generator())
{
if (enumerator == null)
yield break;
for (; ; )
{
//You don't know how to create a value of T,
//and you don't know weather it can be null,
//but you can always have a T[] with null value.
T[] value = null;
try
{
if (enumerator.MoveNext())
value = new T[] { enumerator.Current };
}
catch (Exception e)
{
if (onException(e))
continue;
}
if (value != null)
yield return value[0];
else
yield break;
}
}
}
public static IEnumerable<T> WithExceptionHandler<T>(this IEnumerable<T> orig,
Func<Exception, bool> onException)
{
return RunEnumerator(() =>
{
try
{
return orig.GetEnumerator();
}
catch (Exception e)
{
onException(e);
return null;
}
}, onException);
}
}
will help. Now you can add SkipExceptions:
public static IEnumerable<T> SkipExceptions<T>(this IEnumerable<T> orig){
return orig.WithExceptionHandler(orig, e => true);
}
By using different onException callback, you can do different things
Break the iteration but ignore the exception: e => false
Try to continue iteration: e => true
Log the exception, etc
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.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace TestMaybe
{
class Program
{
static void Main(string[] args)
{
var strings = new string[] { "1", "2", "notint", "3" };
var ints = strings.Select(s => new Maybe<string, int>(s, str => int.Parse(str))).Where(m => !m.nothing).Select(m => m.value);
foreach (var i in ints)
{
Console.WriteLine(i);
}
Console.ReadLine();
}
}
public class Maybe<T1, T2>
{
public readonly bool nothing;
public readonly T2 value;
public Maybe(T1 input, Func<T1, T2> map)
{
try
{
value = map(input);
}
catch (Exception)
{
nothing = true;
}
}
}
}
Edit: depending on the needs of your code, you might also want nothing set to true if the result of map(input) is null.
This is the same answer as Thomas's, but with a lambda & LINQ expression. +1 for Thomas.
Func<string, int?> tryParse = s =>
{
int? r = null;
int i;
if (int.TryParse(s, out i))
{
r = i;
}
return r;
};
var ints =
from s in strings
let i = tryParse(s)
where i != null
select i.Value;
You could just chain the Where and Select method together.
var numbers = strings.Where(s =>
{
int i;
return int.TryParse(s, out i);
}).Select(int.Parse);
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.

Remove doubles from structs array

I know 2 ways to remove doubles from an array of objects that support explicit comparing:
Using HashSet constructor and
Using LINQ's Distinct().
How to remove doubles from array of structs, comparing array members by a single field only? In other words, how to write the predicate, that could be used by Distinct().
Regards,
Well, you could implement IEqualityComparer<T> to pick out that field and use that for equality testing and hashing... or you could use DistinctBy which is in MoreLINQ.
Of course, you don't have to take a dependency on MoreLINQ really - you can implement it very simply:
public static IEnumerable<TSource> DistinctBy<TSource, TKey>
(this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector)
{
// TODO: Implement null argument checking :)
HashSet<TKey> keys = new HashSet<TKey>();
foreach (TSource element in source)
{
if (knownKeys.Add(keySelector(element)))
{
yield return element;
}
}
}
I would probably just loop:
var values = new HashSet<FieldType>();
var newList = new List<ItemType>();
foreach(var item in oldList) {
if(hash.Add(item.TheField)) newList.Add(item);
}
The LINQ answer has been published before. I am copying from Richard Szalay's answer here: Filtering duplicates out of an IEnumerable
public static class EnumerationExtensions
{
public static IEnumerable<TSource> Distinct<TSource,TKey>(
this IEnumerable<TSource> source, Func<TSource,TKey> keySelector)
{
KeyComparer comparer = new KeyComparer(keySelector);
return source.Distinct(comparer);
}
private class KeyComparer<TSource,TKey> : IEqualityComparer<TSource>
{
private Func<TSource,TKey> keySelector;
public DelegatedComparer(Func<TSource,TKey> keySelector)
{
this.keySelector = keySelector;
}
bool IEqualityComparer.Equals(TSource a, TSource b)
{
if (a == null && b == null) return true;
if (a == null || b == null) return false;
return keySelector(a) == keySelector(b);
}
int IEqualityComparer.GetHashCode(TSource obj)
{
return keySelector(obj).GetHashCode();
}
}
}
Which, as Richard says, is used like this:
var distinct = arr.Distinct(x => x.Name);
implement a custom IEqualityComparer<T>
public class MyStructComparer : IEqualityComparer<MyStruct>
{
public bool Equals(MyStruct x, MyStruct y)
{
return x.MyVal.Equals(y.MyVal);
}
public int GetHashCode(MyStruct obj)
{
return obj.MyVal.GetHashCode();
}
}
then
var distincts = myStructList.Distinct(new MyStructComparer());

Is it possible to handle exceptions within LINQ queries?

Example:
myEnumerable.Select(a => ThisMethodMayThrowExceptions(a));
How to make it work even if it throws exceptions? Like a try catch block with a default value case an exceptions is thrown...
myEnumerable.Select(a =>
{
try
{
return ThisMethodMayThrowExceptions(a));
}
catch(Exception)
{
return defaultValue;
}
});
But actually, it has some smell.
About the lambda syntax:
x => x.something
is kind of a shortcut and could be written as
(x) => { return x.something; }
Call a projection which has that try/catch:
myEnumerable.Select(a => TryThisMethod(a));
...
public static Bar TryThisMethod(Foo a)
{
try
{
return ThisMethodMayThrowExceptions(a);
}
catch(BarNotFoundException)
{
return Bar.Default;
}
}
Admittedly I'd rarely want to use this technique. It feels like an abuse of exceptions in general, but sometimes there are APIs which leave you no choice.
(I'd almost certainly put it in a separate method rather than putting it "inline" as a lambda expression though.)
I have come with a small extension when I quickly want to try/catch every iteration of an IEnumerable<T>
Usage
public void Test()
{
List<string> completedProcesses = initialEnumerable
.SelectTry(x => RiskyOperation(x))
.OnCaughtException(exception => { _logger.Error(exception); return null; })
.Where(x => x != null) // filter the ones which failed
.ToList();
}
The extension
public static class OnCaughtExceptionExtension
{
public static IEnumerable<SelectTryResult<TSource, TResult>> SelectTry<TSource, TResult>(this IEnumerable<TSource> enumerable, Func<TSource, TResult> selector)
{
foreach (TSource element in enumerable)
{
SelectTryResult<TSource, TResult> returnedValue;
try
{
returnedValue = new SelectTryResult<TSource, TResult>(element, selector(element), null);
}
catch (Exception ex)
{
returnedValue = new SelectTryResult<TSource, TResult>(element, default(TResult), ex);
}
yield return returnedValue;
}
}
public static IEnumerable<TResult> OnCaughtException<TSource, TResult>(this IEnumerable<SelectTryResult<TSource, TResult>> enumerable, Func<Exception, TResult> exceptionHandler)
{
return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.CaughtException));
}
public static IEnumerable<TResult> OnCaughtException<TSource, TResult>(this IEnumerable<SelectTryResult<TSource, TResult>> enumerable, Func<TSource, Exception, TResult> exceptionHandler)
{
return enumerable.Select(x => x.CaughtException == null ? x.Result : exceptionHandler(x.Source, x.CaughtException));
}
public class SelectTryResult<TSource,TResult>
{
internal SelectTryResult(TSource source, TResult result, Exception exception)
{
Source = source;
Result = result;
CaughtException = exception;
}
public TSource Source { get; private set; }
public TResult Result { get; private set; }
public Exception CaughtException { get; private set; }
}
}
We could eventually go a bit further by having a SkipOnException extension, accepting optionally an exception handler for example.
In case you need Expression instead of lambda function (e.g. when selecting from IQueryable), you can use something like this:
public static class ExpressionHelper
{
public static Expression<Func<TSource, TResult>> TryDefaultExpression<TSource, TResult>(Expression<Func<TSource, TResult>> success, TResult defaultValue)
{
var body = Expression.TryCatch(success.Body, Expression.Catch(Expression.Parameter(typeof(Exception)), Expression.Constant(defaultValue, typeof (TResult))));
var lambda = Expression.Lambda<Func<TSource, TResult>>(body, success.Parameters);
return lambda;
}
}
Usage:
[Test]
public void Test()
{
var strings = new object [] {"1", "2", "woot", "3", Guid.NewGuid()}.AsQueryable();
var ints = strings.Select(ExpressionHelper.TryDefaultExpression<object, int>(x => Convert.ToInt32(x), 0));
Assert.IsTrue(ints.SequenceEqual(new[] {1, 2, 0, 3, 0}));
}
A variation of Stefan's solution for comprehension syntax:
from a in myEnumerable
select (new Func<myType>(() => {
try
{
return ThisMethodMayThrowExceptions(a));
}
catch(Exception)
{
return defaultValue;
}
}))();
Although, it "smells" too, but still this approach can sometimes be used for running code with side-effects inside expression.
When dealing with LINQ you'll commonly find scenarios where your expression could produce undesired side effects. As Jon said, the best way to combat these sort of problems is to have utility methods your LINQ expression can use that will handle these gracefully and in a fashion that won't blow up your code. For example, I have a method I've had to use time to time which wraps a TryParse to tell me if something is a number. There are many other examples of course.
One of the limitations of the expression syntax is that there are a lot of things it can't do either gracefully or even at all without breaking execution out of the expression temporarily to handle a given scenario. Parsing a subset of items in an XML file is wonderful example. Try parsing a complex parent collection with child subsets from an XML file within a single expression and you'll soon find yourself writing several expression pieces that all come together to form the entire operation.
/// <summary>
/// Catch the exception and then omit the value if exception thrown.
/// </summary>
public static IEnumerable<T> Catch<T>(this IEnumerable<T> source, Action<Exception> action = null)
{
return Catch<T, Exception>(source, action);
}
/// <summary>
/// Catch the exception and then omit the value if exception thrown.
/// </summary>
public static IEnumerable<T> Catch<T, TException>(this IEnumerable<T> source, Action<TException> action = null) where TException : Exception
{
using var enumerator = source.GetEnumerator();
while(true)
{
T item;
try
{
if (!enumerator.MoveNext())
break;
item = enumerator.Current;
}
catch (TException e)
{
action?.Invoke(e);
continue;
}
yield return item;
}
}
/// <summary>
/// Catch the exception and then return the default value.
/// </summary>
public static IEnumerable<T> Catch<T>(this IEnumerable<T> source, Func<Exception, T> defaultValue)
{
return Catch<T, Exception>(source, defaultValue);
}
/// <summary>
/// Catch the exception and then return the default value.
/// </summary>
public static IEnumerable<T> Catch<T, TException>(this IEnumerable<T> source, Func<TException, T> defaultValue) where TException : Exception
{
using var enumerator = source.GetEnumerator();
while(true)
{
T item;
try
{
if (!enumerator.MoveNext())
break;
item = enumerator.Current;
}
catch (TException e)
{
item = defaultValue(e);
}
yield return item;
}
}
Usage:
myEnumerable.Select(a => ThisMethodMayThrowExceptions(a)).Catch(e => Console.WriteLine(e.Message));
myEnumerable.Select(a => ThisMethodMayThrowExceptions(a)).Catch(e => default);
myEnumerable.Select(a => ThisMethodMayThrowExceptions(a)).Catch();
myEnumerable.Select(a => ThisMethodMayThrowExceptions(a)).Catch(((InvalidOperationException) e) => Console.WriteLine(e.Message));
myEnumerable.Select(a => ThisMethodMayThrowExceptions(a)).Catch(((InvalidOperationException) e) => default);
I've created small library for this purposes. It's supported exception handling for Select, SelectMany and Where operators.
Usage example:
var target = source.AsCatchable() // move source to catchable context
.Select(v => int.Parse(v)) // can throw an exception
.Catch((Exception e) => { /* some action */ }, () => -1)
.Select(v => v * 2)
.ToArray();
which equivalet to
var target = source
.Select(v =>
{
try
{
return int.Parse(v);
}
catch (Exception)
{
return -1; // some default behaviour
}
})
.Select(v => v * 2)
.ToArray();
It's also possible to handle several types of exceptions
var collection = Enumerable.Range(0, 5)
.AsCatchable()
.Select(v =>
{
if (v == 2) throw new ArgumentException("2");
if (v == 3) throw new InvalidOperationException("3");
return v.ToString();
})
.Catch((ArgumentException e) => { /* */ }, v => "ArgumentException")
.Catch((InvalidOperationException e) => { /* */ }, v => "InvalidOperationException")
.Catch((Exception e) => { /* */ })
.ToList();
wrap ThisMethodMayThrowExceptions with a new function,
myEnumerable.Select(a => ThisMethodMayThrowExceptions(a)); //old
myEnumerable.Select(a => tryCall(ThisMethodMayThrowExceptions,a)); //new
it's a generic function, with try catch inside.
T2 tryCall<T1, T2>(Func<T1, T2> fn, T1 input, T2 exceptionValue = default)
{
try
{
return fn(input);
}
catch
{
return exceptionValue;
}
}
var numbers = new [] {"1", "a"};
numbers.Select(n => tryCall(double.Parse, n)); //1, 0
numbers.Select(n => tryCall(double.Parse, n, double.NaN)); //1, NaN
I believe this is the correct answer since it allows you to handle the troublesome item and it is filtered from the end result.
public static class IEnumerableExtensions {
public static IEnumerable<TResult> SelectWithExceptionHandler<T, TResult>(this IEnumerable<T> enumerable, Func<T, TResult> func, Action<T, Exception> handler)
=> enumerable
.Select(x => {
try {
return (true, func(x));
} catch (Exception error) {
handler(x, error);
}
return default;
})
.Where(x => x.Item1)
.Select(x => x.Item2);
}

Categories