我只是改写了这个:

if (budgetRemaining != 0 || totalOpenInvoices != 0)
{
}


喜欢这个:

if (new[] { budgetRemaining, totalOpenInvoices }.Any(c => c != 0))
{
}


如果我看过在我加速使用Linq之前,这会让我感到困惑。现在,我一直在学习函数式编程并使用Linq,这看起来很自然,但这会牺牲简单性吗?

评论

totalOpenInvoices代表未结发票金额的总和,还是仅仅是未结发票的数量?

这是每个未结发票的金额之和

IMO,您的重写很难阅读。

这是“我刚刚学到了一些非常酷的东西,让我在遇到的第一件事上尝试一下”的情况。到过那里。完成了。不值得。

这种语法对于不熟悉函数式编程的人来说很奇怪。但是,当您要检查两个以上的术语时,这可能是值得的。还将lambda表达式提取到命名属性中可能使其更具可读性,并请喜欢流利样式的人使用。私人Func IsNotZero {get {return c => c!= 0; }} ... if(new [] {budgetRemaining,totalOpenInvoices,otherThings,moreStuff等,...} .Any(IsNotZero)){}

#1 楼

似乎是在用别克飞向我扑来。第一种形式看起来很简洁,变量名具有很强的描述性。第二种形式创建了一个新对象(数组),该对象最终将必须进行GC处理,并引入一个新的lambda变量c,该变量似乎不再具有描述性。

评论


\ $ \ begingroup \ $
simple-talk.com/dotnet/performance / ...除非收集时仍在使用该对象,否则不会“收集垃圾”。也就是说,如果不使用它,则不会将其移至Gen1,而只会将其擦除。
\ $ \ endgroup \ $
–taylonr
2011-12-22 17:47

\ $ \ begingroup \ $
另一种方法:如果不使用它,则将其收集。如果仍在使用,它将移至第一代。但关键是,创建了一个数组,但没有条件在其他任何地方引用它,但条件if语句使它可以立即被收集。
\ $ \ endgroup \ $
–Jesse C. Slicer
2011-12-22 18:05

\ $ \ begingroup \ $
在这种情况下,在此处使用Any()方法是过大的。对于较长的情况(可能有4个或更多个单独的条件),或者如果您恰好碰巧有收藏夹,则应保留它。
\ $ \ endgroup \ $
–杰夫·梅卡多(Jeff Mercado)
2011-12-22 19:40

\ $ \ begingroup \ $
通用汽车打电话来了,他们不喜欢你打电话给他们的别克苍蝇拍。 :-)
\ $ \ endgroup \ $
– LarsTech
2011-12-22 21:55

#2 楼

花式不是这个词。疯了吧。听说过KISS原则吗?保持简单愚蠢。当然,除非您是故意地寻找使代码看起来模糊不清,使可执行文件膨胀的方法。

评论


\ $ \ begingroup \ $
是的。解决方案应该尽可能简单(但不要简单)。
\ $ \ endgroup \ $
–乔治·达基特(George Duckett)
2011-12-23 11:56



#3 楼

作为Java开发人员,第一个更容易阅读。这也可能会造成混淆:为什么作者使用LINQ而不是简单的||?这让我想起了仪器的法则:“如果您只用锤子,一切都像钉子。”无论如何,也许值得为这种情况创建一个名字明确的局部变量帮助读者:

boolean needName = budgetRemaining != 0 || totalOpenInvoices != 0
if (needName) {
    ...
}


创建命名的局部变量也将提高第二个版本的可读性。

评论


\ $ \ begingroup \ $
我希望用私有函数needName()替换局部变量needName
\ $ \ endgroup \ $
– Dorus
2011-12-25 13:08

#4 楼

在C#中,您会遇到一些语法上的杂音,这使该代码的可读性更加差,从而大大抵消了这种低收益抽象的好处。即使使用像Haskell这样以抽象能力闻名的语言,您也可以做的最好的事情是:

any (/= 0) [budgetRemaining, totalOpenInvoices]


虽然可以使用,但仍比

budgetRemaining /= 0 || totalOpenInvoices /= 0


#5 楼

如果可能的话,我可能更喜欢做这样的事情:

IEnumerable<decimal> GetBalances()
{
    decimal budgetRemaining = 0M;

    // calculate budget remaining

    yield return budgetRemaining;

    decimal totalOpenInvoices = 0M;

    // calculate the total of the open invoices

    yield return totalOpenInvoices;

    // ... calculate and yield any other balances that require consideration
}


,然后我可以这样写if语句:

    if (this.GetBalances().Any(balance => balance != 0M))
    {
    }


注意:我怀疑如果我只需要检查2个余额,我会使用这种方法,但是如果我有很多需要检查的不同余额,我可能会这样做。

原始答案

编辑:对该问题的评论表明totalOpenInvoices变量代表未结发票的总金额,因此,此答案实际上不适用于该问题。不过,我将其保留在此处,因为我认为该参数对于此答案中描述的情况仍然有效。

totalOpenInvoices是否代表未结发票金额的总和,或者

如果是后者,那么我不喜欢这种方法的原因之一是因为您正在比较苹果和桔子。您说的是支票budgetRemaining != 0本质上与支票totalOpenInvoices != 0类似,唯一的区别是输入变量(budgetRemaining或totalOpenInvoices)。

我将尝试说明为什么不这样做通过以不同方式分解if语句对我来说很有意义。我将把!= 0代码移到一个名为stillHasMoney的委托中:

Func<decimal, bool> stillHasMoney = (amount) => amount != 0;

if (stillHasMoney(budgetRemaining) || stillHasMoney(totalOpenInvoices))
{
}


现在,此代码仍然有意义吗?如果totalOpenInvoices代表未结发票的数量,而不是未结发票的金额之和,那么此代码对我来说似乎不正确。这就像在说:“我有5只乌龟,捐出了2只。还剩多少钱?”同样,此代码表示“我有5张未结清发票并已结清2张。还剩多少钱?”当然,与乌龟相比,发票更容易将钱转换成金钱,但是重点是,您是否关心未结发票的数量或它们的货币价值总和?

#6 楼

假定budgetRemainingtotalOpenInvoices都保证为非负数,则可以这样写:

if (budgetRemaining + totalOpenInvoices > 0)
{
}


当然,虽然简化了代码,但却牺牲了清晰度和可维护性。所以不要那样做。 :)

#7 楼

有时候,拥有像

bool IsAlive(..)
{
 return (budgetRemaining != 0 || totalOpenInvoices != 0);
}
这样的函数会更方便,它并不直接适用于您的问题,只是附带说明:)