Do nothing when "other side" of ternary operator is reached?

27.1k views Asked by At

Note: I've seen this question asked sometimes before (a, b, c), but neither of these was in C#, nor helpful.

Assume I'm using the ? : ternary operator like this (to do nothing when false is the case):

r==5? r=0 : <nothing> ;

I'm getting an error. Putting something there will obviously solve the problem. How can I still keep the other side empty without making some random empty function?

6

There are 6 answers

9
Jon Skeet On BEST ANSWER

You can't. The whole point of the conditional ?: operator is that it evaluates an expression. You can't even just use:

Foo() ? Bar() : Baz();

... because that isn't a statement. You have to do something with the result... just like when you access a property, for example.

If you want to only execute a piece of code when a specific condition is met, the ?: operator isn't what you want - you want an if statement:

if (foo)
{
    bar();
}

It's as simple as that. Don't try to twist the conditional operator into something it's not meant to be.

0
meJustAndrew On

Why would you want to use a ternary when you obviously need two parameters? You can simply use an if statement:

 if(Condition())Action();
1
shA.t On

I can suggest an extension method like this:

public static T ChangeOn<T>(this T variable, bool condition, T newValue)
{
    return condition ? newValue : variable;
}

And use it like this:

var result = r.ChangeOn(r == 5, 0);
//or: r = r.ChangeOn(r == 5, 0); for self change
0
GilesDMiddleton On

You can now achieve this using the Discard operator, if you really want to.

public class Program
{
    public static void Main()
    {
        int r=5;
        _ = r==5 ? r=0 : 0;
        Console.WriteLine($"{r}");
        // outputs 0
    }
}

You can now also do

_=Foo() ? Bar() : Baz();

As long as Bar and Baz return the same or convertible type.

0
Osoraa On

Just pass undefined to the side you want to do nothing with.

// An array of numbers
let test = [12, 929, 11, 3]

// Adds 100 to the element in the text array if it is divisible by 3.
test.forEach(function (element, index) {
  element % 3 ? undefined : test[index] += 100;
});

// Logs the test array to the screen
console.log(test);

Passing "undefined" to the side of the ternary expression you want to disregard does exactly that.

0
Fᴀʀʜᴀɴ Aɴᴀᴍ On

The other answers are correct, but they miss out a key point which I think is the main thing you're having an issue with. The thing to notice is that

r = 0

apart from assigning r a value, returns the same value too. You can think of it like a function. You can call a function, which maybe does some other stuff apart from returning a value, which you may or may not put into use.

Take for example:

int square(int n)
{
    // Now you can do other things here too. Maybe you do something with the UI in here:
    Console.WriteLine("Calculating...");
    // ^ Now thing of the above code as assigning a value to a variable.
    return n * n;
    // But after assigning the value, it also returns the value...
}

So, now suppose you may have two usage cases:

var x = square(2);
// -- OR --
square(2);

Note that both statements output 'Calculating...' but the former assigns a value of 2 * 2 or 4 to x.

Even better, let's say we have a function:

int AssignValueToVariable(out int variable, int value)
{
    variable = value;
    return value;
}

Now the function is obviously redundant, but let's suppose we can use it for better understanding. Assume that it is equivalent to the assignment = operator.

That said, we can come back to our scenario. The ternary operator <condition> ? <true expression> : <false expression> takes in two expressions to return on the basis of a specified condition. So, when you write:

r == 5 ? r = 0 : r = 2; // Let's suppose the third operand to be r = 2

it is equivalent to:

r == 5 ? AssignValueToVariable(r, 0) : AssignValueToVariable(r, 2)

both of which are essentially:

r == 5 ? 0 : 2

That brings back the hard and fast rule that the operands must be expressions as the entire thing must boil down to an expression. So, you can get a kind of 'nothing' equivalent for an expression by using its default value.

Or, as the other answers mention, use an if statement, straight and simple:

if (r == 5)
    r = 0;

Extrapolating from the code you provided, I'd guess you're doing something with the evaluated expression. You can store the value in a separate variable result and do whatever with it:

int result;
if (r == 5)
    result = r = 0; // This sets the value of both result and r to 0

Now, you can substitute result for your previous expression you wanted, i.e., r == 5 ? r = 0 : <nothing> // Pseudo-code.

Hope it helps :)