将for循环转换为LINQ

时间:2013-03-04 15:34:42

标签: c# linq try-catch

如果我有以下工作代码:

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){ ... }

并希望将其重新制作成LINQ,如何管理 try-catch ?如果我把它放在下面的表达式中,它就不会让我感到困惑。我的建议是迁移捕获方法,但我不确定它是多么优化/推荐。可以说一下还是取决于场景的具体情况?

IEnumerable<String> strings = source.Select(e => Fetch(e));

public MyClass Fetch(Object source){ try{ ... } catch(){ ... } }

像这样的伪代码很酷。我正在考虑方法.First(),它是更有效的兄弟.FirstOrDefault(),但有额外的容量。

IEnumerable<String> strings = source.Select(e => Fetch(e)).Excepted(...);

我离开了吗?

4 个答案:

答案 0 :(得分:2)

最好的办法是将try / catch块移动到单独的方法中,并将该方法用作选择器。

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);

答案 1 :(得分:0)

您将获得与原始代码相同的行为

List<String> results = source.Select(e => { try
                                            {
                                                return Fetch(e);
                                            }
                                            catch(Exception)
                                            {
                                                 return MyClass("poof");
                                            }
                                          }).ToList();

但我认为你应该重新考虑使用try / catch这种方式。它具有严重的性能成本,并非旨在处理非特殊情况。如果可以获取e并执行类似

的操作,请先检查一下
List<String> results = source.Where(e => IsFetchable(e))
                             .Select(e => Fetch(e))
                             .ToList();

答案 2 :(得分:0)

最简单的解决方案就是做你已经做过的事情 即你可以包括代码块。

IEnumerable<String> strings = source.Select(e =>
{
try
  {
    return Fetch(e);
  }
catch
 {
    return new MyClass("poof");
 }
}
);

答案 3 :(得分:0)

我认为您无法创建Excepted类,但您可以使用两个选择器创建Select方法,其中一个用于错误情况:

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

然后它会允许你这样做:

var results = source.Select(item => Fetch(item)
    , item => new MyClass("poof!"))
    .ToList();

您的辅助选择器也可以将异常作为参数,如果这是合适的。