Tanner Fix-It Smith
Tanner Fix-It Smith

Reputation: 95

Operator To Return if one and ONLY One Argument is True

I'm making an if statement in C# that I would like to return true if ONLY one of the parameters is true. I'll use || in the example because that's the closest thing I can think of:

int a = 1;
int b = 2;
int c = 3;

if(a == 1 || b == 2)
{
Console.Log("The first statement is true")
}

if(a == 1 || b == 3)
{
Console.Log("The second statement is true")
}

if(a == 0 || b == 0 || c == 3)
{
Console.Log("The third statement is true")
}

if(a == 1 || b == 0 || c == 3)
{
Console.Log("The fourth statement is true")
}

//Output:
//The second statement is true
//The third statement is true

Again, think of the || as the operator I'm looking for. Does such an operator exist, or should I define my own boolean function?

Upvotes: 3

Views: 5480

Answers (3)

p.s.w.g
p.s.w.g

Reputation: 149068

For 2 operands, the XOR (^) operator will do this. From MSDN:

For bool operands, ^ computes the logical exclusive-or of its operands; that is, the result is true if and only if exactly one of its operands is true.

For three or more operators, Jon is correct, you will simply need to loop through the conditions. However, if there are very many conditions to check (or just a few very expensive conditions), you could possibly achieve a performance improvement by short-circuiting the result when the second true is found, like so:

var conditions = ...
if (conditions.Where(x => x).Take(2).Count() == 1) 

Or if you'd prefer something less cryptic, perhaps an extension method

public static bool ExactlyOne(this IEnumerable<T> source, Func<T, bool> predicate)
{
    var found = false;
    foreach(var x in source)
    {
        var result = predicate(x);
        if (result && found) {
            return false;
        }
        found = result;
    }

    return found;
}

var conditions = ...
if (conditions.ExactlyOne(x => x)) 

Upvotes: 0

Jon Skeet
Jon Skeet

Reputation: 1503489

For two expressions, you can just use XOR:

if (a == 1 ^ b == 0)

For more than two, you could do something like:

if (new[] { a == 1, b == 0, c == 2 }.Count(x => x) == 1)

That basically counts all the "true" elements of the array constructed from the expressions, and checks that the count is 1.

Admittedly that evaluate all the conditions first, and will count all of them even if the first two are true (so the final one is irrelevant). If that ends up being expensive for you, there are more complex alternatives, but I'd definitely stick to something like this unless it's actually a problem.

Upvotes: 12

Xiaoy312
Xiaoy312

Reputation: 14477

There is no such operator. However you can try this :

var statements = new[] { a == 0, b == 2, c == 2 };
switch (statements.Count(x => x))
{
    case 0: Console.WriteLine("None of statement is true"); break;
    case 1:
        Console.WriteLine("The {0} statement is true", 
            new[] { "first", "second", "third" }.Skip(statements.TakeWhile(x => !x).Count()).First());
        break;

    default:
        Console.WriteLine("More than one statement is true");
        break;
}

Output :

The second statement is true

Upvotes: 0

Related Questions