Geo*_*ett 21 c# linq ienumerable exception-handling word-wrap
我想要一个通用的解决方案,但作为一个例子,假设我有一个IEnumerable<string>,其中一些可以解析为整数,有些不能.
var strings = new string[] { "1", "2", "notint", "3" };
Run Code Online (Sandbox Code Playgroud)
显然,如果我这样做,Select(s => int.Parse(s, temp))它会在枚举时抛出异常.
在这种情况下,我可以先做.All(s => int.TryParse(s, out temp)),但我想要一个通用的解决方案,我不必枚举IEnumerable两次.
理想情况下,我希望能够执行以下操作,它调用我的魔术异常跳过方法:
// 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();
Run Code Online (Sandbox Code Playgroud)
我该如何编写SkipExceptions()扩展方法?
一个SelectSkipExceptions()方法的一些很好的答案,但我不知道是否SkipExceptions()可以创建一个方法,沿着相同的行AsParallel().
Urb*_*Esc 17
这个怎么样(你可能想给这个特殊的Select Extension一个更好的名字)
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;
}
}
Run Code Online (Sandbox Code Playgroud)
编辑5 添加了一个using语句,感谢评论中的建议
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;
}
}
}
Run Code Online (Sandbox Code Playgroud)
但是,这依赖于尚未创建的传入IEnumerable(因此已经抛出异常)作为前面Function的列表.例如,如果你这样调用它可能不会起作用:选择(..).ToList().SkipExceptions()
创建一个TryParseInt返回以下内容的方法Nullable<int>:
int? TryParseInt(string s)
{
int i;
if (int.TryParse(s, out i))
return i;
return null;
}
Run Code Online (Sandbox Code Playgroud)
并在您的查询中使用它:
var numbers = strings.Select(s => TryParseInt(s))
.Where(i => i.HasValue)
.Select(i => i.Value);
Run Code Online (Sandbox Code Playgroud)
另见Bill Wagner的这篇文章,它提出了一个非常相似的案例.
现在,我不认为你可以编写类似于泛型SkipExceptions方法的东西,因为你会太晚捕获异常,它会结束Select循环......但是你可能会编写一个SelectSkipException方法:
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;
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
2530 次 |
| 最近记录: |