简化LINQ表达式

时间:2013-10-23 15:16:21

标签: c# linq

我有一部分我真的不喜欢的代码,如果有可能以某种方式简化它 - 会非常好。

A a; // I want to get rid of this variable
if((a = collection.FirstOrDefault(x => x.Field == null)) != null)
{
  throw new ScriptException("{0}", a.y); //I need to access other field of the object here, that's why I had to declare a variable outside of the expression
}

7 个答案:

答案 0 :(得分:7)

如果要组合变量赋值和定义,则可以使代码更具可读性:

A a = collection.FirstOrDefault(x => x.Field == null);

if(a != null)    
   throw new ScriptException("{0}", a.y);

答案 1 :(得分:7)

不是找到匹配和处理的第一个项目,而是将结果视为集合。对使用foreach匹配的所有项目Where。由于异常将使您退出循环,因此最终结果是相同的,只需使用更清晰的代码:

foreach(var a in collection.Where(x => x.Field == null))
    throw new ScriptException("{0}", a.y);

如果你想让读者更清楚,循环最多只执行一次,你可以在那里添加一个Take调用来澄清代码而不做任何功能改变:

foreach(var a in collection.Where(x => x.Field == null).Take(1))
    throw new ScriptException("{0}", a.y);

这也可以更容易地聚合所有无效项目,而不是第一次:

var exceptions = collection.Where(a => a.Field == null)
    .Select(a => new ScriptException("{0}", a.y))
    .ToList();
if (exceptions.Any())
    throw new AggregateException(exceptions);

答案 2 :(得分:2)

您无法避免声明变量,因为您需要在if之外进行分配,然后引用内部的值。 (唯一的方法是两次执行过滤器,这可能很昂贵)。

也就是说,您可以利用这个优势并使代码更具可读性:

A a = collection.FirstOrDefault(x => x.Field == null); // assign here
if(a != null) // more easily-readable comparison here
{
  throw new ScriptException("{0}", a.y); 
}

答案 3 :(得分:1)

在这种情况下你无法摆脱A a。您需要存储从LINQ语句返回的值以便稍后使用,并且与using块不同,if语句不允许您在其表达式中定义变量。

就个人而言,我会这样做:

A a = collection.FirstOrDefault(x => x.Field == null);
if(a != null)
{
    throw new ScriptException("{0}", a.y);
}

答案 4 :(得分:1)

所以你的逻辑是:如果有任何没有字段的项目,抛出异常。

var a = collection.Where(x => x.Field == null);
if(a.Any())
{
  throw new ScriptException("{0}", a.First().y);
}

更好的方法可能是整理它们:

var a = collection.Where(x => x.Field == null).Select(x => x.y);
if(a.Any())
{
  throw new ScriptException("{0}", string.Join(',', a));
}

这样你就可以看到所有的实例。

答案 5 :(得分:0)

您可以使用.Select删除a的外部引用,但结果仍然是一团糟:

collection.Where(x => x.Field == null)
    .Select(a => string.Format("{0}", a.y))
    .Take(1).ToList().ForEach(msg => 
        throw new ScriptException(msg);
    );
如果没有匹配项,

Take(1)将返回一个空的枚举,以便ForEach中的块将运行零次或一次。

答案 6 :(得分:0)

这对你有用吗?它很难看,但你可以在lambda中抛出异常。

collection.FirstOrDefault(x => { 
                                 if(x.Field == null)
                                 {
                                       throw new ScriptException("{0}", x.y);
                                 }
                                 return false;
                                }
                          );