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

6

15

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?

Outroar answered 14/12, 2016 at 15:57 Comment(6)
Can you give a non-psuedo code example?Garett
Possible duplicate of Do nothing keyword in C#?Dysgenics
What is the use of a ternary (conditional) operator when you know that you don't want to do anything for one case?Extraction
@Garett r==5? r=0 : <nothing> ;Outroar
If you really want to use the conditional expression you could use r = (r == 5 ? 0 : r) but you should just use an if statement i.e. if (r == 5) { r = 0; }Judsonjudus
@Judsonjudus That's probably the best answer. Thanks.Outroar
T
35

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.

Trisomic answered 14/12, 2016 at 15:59 Comment(9)
It's like saying you either want to call bar().Saturday
My example was kinda off, I updated it to what it's supposed to be now.Outroar
@devRicher: The principle remains the same.Saturday
@devRicher: That's even worse, as your 2nd operand is now a side-effecting one. What are you actually trying to accomplish? It sounds like you want if (r == 5) { r = 0; } . If that's what you want, why not use it?Trisomic
@Outroar the only solution to that is r==5 ? r=0 : r; Even then, it's objectively better and more readable to use if(r==5)r=0;Stirps
Well, I'm trying to just make a counter. I guess @AlfieGoodacre 's comment might help.Outroar
@devRicher: You mean you want it to go 0, 1, 2, 3, 4, 0, 1, 2, 3, 4 etc? If so, you want: r = (r + 1) % 5;. Again, no need for a conditional operator.Trisomic
Such snarky comments, and even the answer finishes with some snark just because. As if the conditional operator is some holy functionality that has one purpose and one purpose only. i could absolutely see myself use it for something along the ways of a null check. myObject != null ? myFunction(myObject);. Yes this doesn't work i know.Encincture
@Enok82: It's not about it being "holy" (and I find it interesting that in a comment objecting to snark, you inserted more snark than I've seen anywhere else in this thread), but it is intended to compute a result rather than being a shorthand for executing different statements. While it could have been designed differently, I see nothing wrong with saying "it wasn't designed to do what you're trying to do".Trisomic
D
4

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

 if(Condition())Action();
Diphenylamine answered 14/12, 2016 at 16:3 Comment(0)
H
2

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 :)

Higgler answered 15/12, 2016 at 19:56 Comment(0)
D
2

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.

Democratic answered 26/2, 2019 at 22:29 Comment(0)
G
1

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
Gerrygerrymander answered 18/12, 2016 at 6:48 Comment(1)
Because many are much more proficient at reading logical symbols quickly and accurately than an english statement when looking at an entire monitor of code. Syntax that can be read efficiently is efficient coding. This includes native english speakers. Anything involving many parenthesis, which extend above and below lowercase letters can dramatically increase the visual noise across an entire screen.Imagism
S
0

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.

Sequent answered 15/1, 2022 at 19:32 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.