Являются ли эти if-заявления слишком интересными?

Я просто переписал это:

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

Вот так:

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

Если бы я видел это, прежде чем я набросился на Линка, это бы смутило меня. Теперь, когда я изучаю функциональное программирование и использую Linq, это кажется естественным, но приносит в жертву простоту?

30 голосов | спросил Aaron Anodide 22 ThuEurope/Moscow2011-12-22T21:10:46+04:00Europe/Moscow12bEurope/MoscowThu, 22 Dec 2011 21:10:46 +0400 2011, 21:10:46

7 ответов


48

Кажется, что я летаю с Бьюиком. Первая форма выглядит довольно кратким, и имена переменных довольно описательны. Вторая форма создает новый объект (массив), который в конечном итоге должен быть GC'd и вводит новую лямбда-переменную, c, которая больше не выглядит описательной.

ответил Jesse C. Slicer 22 ThuEurope/Moscow2011-12-22T21:39:12+04:00Europe/Moscow12bEurope/MoscowThu, 22 Dec 2011 21:39:12 +0400 2011, 21:39:12
29

Необычность - это не слово для этого. Это безумие. Когда-либо слышал о принципе KISS? Держать его просто глупо. Если, конечно, вы не намерены искать способы, чтобы ваш код выглядел запутанным, а ваш исполняемый файл раздувался.

ответил Mike Nakis 23 FriEurope/Moscow2011-12-23T00:58:35+04:00Europe/Moscow12bEurope/MoscowFri, 23 Dec 2011 00:58:35 +0400 2011, 00:58:35
22

Как разработчик Java, первое гораздо легче читать. Это тоже может ввести в заблуждение: почему автор использует LINQ вместо простого ||? Это напоминает мне закон инструмента : «Если у вас все есть молот, все выглядит как гвоздь».

В любом случае, возможно, стоит создать хорошо названную локальную переменную для условия, которое могло бы помочь читателям:

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

Создание именованной локальной переменной улучшит читаемость второй версии.

ответил palacsint 22 ThuEurope/Moscow2011-12-22T21:43:56+04:00Europe/Moscow12bEurope/MoscowThu, 22 Dec 2011 21:43:56 +0400 2011, 21:43:56
8

В C # у вас есть синтаксический шум, который делает этот код еще менее удобочитаемым, перевыполняя преимущества такой низкоурожайной абстракции с большим отрывом. Даже на таком языке, как Haskell, известном своей силой абстракции, самое лучшее, что вы можете сделать, это следующее:

any (/= 0) [budgetRemaining, totalOpenInvoices]

Который, хотя и полезен, еще длиннее

budgetRemaining /= 0 || totalOpenInvoices /= 0
ответил Rotsor 23 FriEurope/Moscow2011-12-23T03:24:18+04:00Europe/Moscow12bEurope/MoscowFri, 23 Dec 2011 03:24:18 +0400 2011, 03:24:18
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))
    {
    }

Примечание. Я сомневаюсь, что я бы использовал этот подход, если мне нужно было проверить только два баланса, но я мог бы сделать это, если бы у меня было очень много разных балансов, которые нужно было проверить.

Оригинальный ответ

EDIT: комментарий к вопросу указывает, что переменная totalOpenInvoices представляет собой общую денежную сумму открытых счетов-фактур, поэтому этот ответ действительно не применяется к вопросу. Однако я оставлю это здесь, так как считаю, что аргумент все равно будет действительным для ситуации, описанной в этом ответе.

Содержит ли totalOpenInvoices сумму денежной суммы открытых счетов-фактур, или это просто количество открытых счетов-фактур?

Если последнее, то одной из причин, почему мне не нравится этот подход, является то, что вы сравниваете яблоки и апельсины. Вы говорите, что проверка budgetRemaining != 0 похожа по своей природе на check totalOpenInvoices != 0, и единственная разница - входная переменная (либо budgetRemaining, либо totalOpenInvoices ).

Я попытаюсь проиллюстрировать, почему это не имеет смысла для меня, нарушая утверждение if по-другому. Я переведу код != 0 в делегат под названием stillHasMoney:

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

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

Теперь, действительно ли этот код имеет смысл? Если totalOpenInvoices представляет количество открытых счетов-фактур, а не сумму денежной суммы открытых счетов-фактур, то этот код мне кажется неправильным. Это как сказать: «У меня было 5 черепах и раздавалось 2. Сколько денег осталось?» Аналогичным образом, этот код говорит: «У меня было 5 открытых счетов и закрыто 2. Сколько осталось денег?» Разумеется, счета-фактуры переводят на деньги легче, чем черепахи, но дело в том, что вы заботитесь о количестве открытых счетов-фактур или сумме их денежной стоимости?

ответил Dr. Wily's Apprentice 22 ThuEurope/Moscow2011-12-22T23:34:39+04:00Europe/Moscow12bEurope/MoscowThu, 22 Dec 2011 23:34:39 +0400 2011, 23:34:39
3

Предполагая, что оба budgetRemaining и totalOpenInvoices гарантированы как неотрицательные, вы можете написать:

if (budgetRemaining + totalOpenInvoices > 0)
{
}

Конечно, хотя это упрощает код, он жертвует ясностью и ремонтопригодностью. Так что не делай этого. :)

ответил Todd Lehman 5 Jam1000000amThu, 05 Jan 2012 03:44:03 +040012 2012, 03:44:03
1

Иногда проще иметь такую ​​функцию, как

bool IsAlive(..)
{
 return (budgetRemaining != 0 || totalOpenInvoices != 0);
}

это не относится непосредственно к вашему вопросу, просто сторона примечания:)

ответил Dmitry 4 Jpm1000000pmWed, 04 Jan 2012 20:59:37 +040012 2012, 20:59:37

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132