我想要一个通用解决方案,但作为示例,假设我有一个IEnumerable<string>,其中有些可以解析为整数,有些则不能解析为整数。

var strings = new string[] { "1", "2", "notint", "3" };

显然,如果我做了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();

如何编写SkipExceptions()扩展方法?

对于SelectSkipExceptions()方法有一些很好的答案,但是我想知道是否可以按照与SkipExceptions()相同的方式创建AsParallel()方法。

最佳答案

怎么样(您可能想给这个特殊的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;
        }
    }

编辑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;
           }
        }
    }

但是,这依赖于前面的Function尚未将传入的IEnumerable创建为列表(因此已经抛出Exception)。例如。如果您这样称呼它,那么可能不起作用:Select(..)。ToList()。SkipExceptions()

关于c# - LINQ查询执行投影,跳过或包装将源抛出到IEnumerable.GetNext()的异常,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/7188623/

10-13 06:29
查看更多