1

如果我有以下工作代码:

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

4 回答 4

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);
于 2013-03-04T15:38:01.433 回答
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();
于 2013-03-04T15:40:41.743 回答
0

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

IEnumerable<String> strings = source.Select(e =>
{
try
  {
    return Fetch(e);
  }
catch
 {
    return new MyClass("poof");
 }
}
);
于 2013-03-04T15:41:26.463 回答
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();

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

于 2013-03-04T15:41:33.860 回答