Есть ли сокращенный способ сказать, что если bool уже истинно, не присваивайте false?

Я уже пытался это найти, но ничего не нашел и не знаю, как это будет называться. Логическое объединение?

У меня есть несколько методов, вызываемых параллельно, каждый из которых возвращает логическое значение, указывающее на сбой. Есть ли способ присвоить каждому из них одно логическое значение, чтобы, если какой-либо из них возвращал true, общее логическое значение правда.

ИЕ:

    Boolean exceptionOccurred = false;

    Parallel.Invoke(
       () => exceptionOccurred = MethodA(),
       () => exceptionOccurred = MethodB(),
       () => exceptionOccurred = MethodC(),
       () => exceptionOccurred = MethodD(),
    );

с этим кодом как есть, если метод A вернул true, а остальные методы вернули false, в зависимости от того, какой из них вернулся первым/последним, ему почти всегда будет присвоено значение false. Но я хочу знать, вернет ли кто-нибудь из них истину.

Одним из решений является присвоение каждому уникальному логическому значению, а затем проверка всех логических значений. Но я надеялся на что-то вроде побитового оператора bool +=, который не устанавливал бы дляExceptionOccurred значение false, если оно уже было истинным. Есть ли способ сделать это?

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

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

exceptionOccurred |= MethodA()
shingo 20.03.2024 15:22
Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
1
102
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

Вы можете использовать то, что называется короткое замыкание. Если значение, которое вы хотите сохранить, равно true, вам следует использовать оператор or.

bool exceptionOccurred = false;
exceptionOccurred = exceptionOccurred || methodA();
exceptionOccurred = exceptionOccurred || methodB();

Если вы хотите сохранить вывод false, вам также необходимо использовать оператор and, а также начинать с true.

bool noExceptionOccurred = true;

noExceptionOccurred = noExceptionOccurred && methodA();
noExceptionOccurred = noExceptionOccurred && methodB();

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

Robert Harvey 20.03.2024 15:26

Я совершенно упустил из виду, что они работают параллельно. Да, вы правы, я редактирую свой ответ.

Valerij Dobler 20.03.2024 15:32

Это имеет состояние гонки и может привести к возникновению исключений, пока exceptionOccurred имеет значение false.

Servy 20.03.2024 15:39

«Что является сокращением» здесь неверно (ни в одном из ваших примеров). exceptionOccurred |= methodA() всегда будет выполняться methodA(), независимо от значения exceptionOccurred — это не короткое замыкание.

Jon Skeet 20.03.2024 15:43

Вы можете реализовать потокобезопасное решение, воспользовавшись Interlocked.Increment (см. https://learn.microsoft.com/en-us/dotnet/api/system.threading.interlocked.increment?view=net-8.0). .

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

   int errors = 0;
   Parallel.Invoke(
       () => if (MethodA()) { Interlocked.Increment(ref errors); },
       () => if (MethodB()) { Interlocked.Increment(ref errors); },
       () => if (MethodC()) { Interlocked.Increment(ref errors); },
       () => if (MethodD()) { Interlocked.Increment(ref errors); },
    );
   Boolean exceptionOccurred = (errors == 0);

Не хватает ref в Interlocked.Increment(ref errors).

CookedCthulhu 20.03.2024 15:45
Ответ принят как подходящий

Параллельная запись в одно и то же место назначения безопасна/полезна только в том случае, если в место назначения всегда записывается один и тот же результат. К счастью, ваш случай — одно из таких исключений. Таким образом, следующее является потокобезопасным и укажет, произошел ли сбой хотя бы одного метода. Он также самый быстрый, поскольку не требует синхронизации:

() =>
{
    var failure = MethodA();
    if (failure) exceptionOccurred = true;
}

a |= b или a = a || b небезопасно. Учтите следующее:

Thread1 reads a [false]
Thread1 reads b [true]
Thread2 reads a [false]
Thread2 reads b [false]
Thread1 writes true
Thread2 writes false

Другие вопросы по теме