? operator without else-part
Asked Answered
S

4

50

I use C# ? operator when I have if-statements that affects one row and it's all good. But lets say I have this code (using classic if-statements):

if(someStatement)
{
    someBool = true;  //someBools value is unknown
}
else
{
    //Do nothing
}

This can be achieved on a one-liner by doing:

someBool = (someStatement) ? true : someBool;

But why can't I do something like this:

someBool = (someStatement) ? true : ;
//or possibly
someBool = (someStatement) ? true;

Is this possible in some way? If it is, is there any benefits of using one method over the other? And if not, why shouldn't you be able to do it?

Setscrew answered 24/7, 2014 at 13:18 Comment(6)
What do you expect the expressions (someStatement) ? true : and (someStatement) ? true to evaluate to?Discrepant
@O.R.Mapper true if someStatement is true and unchanged if someStatement is false (this question is purely hypothetical, not an actuall problem I have)Setscrew
What is unchanged? The expression must evaluate to a concrete value, in this case, of type bool - that is, either true or false.Discrepant
@O.R.Mapper unchanged means that if someBool was true before, then it will still be true. If it was false, then it will still be false.Setscrew
Neither the statement (someStatement) ? true : nor the statement (someStatement) ? true can possibly know what the value of someBool is. They can only return a value based on the input, that is, based exclusively on someStatement - or a constant, which is either true or false. To use your expression syntax in an equally valid context for expressions, imagine this call: DoSomethingWithBool(someStatement ? true); - What argument would be passed to DoSomethingWithBool if someStatement is false here?Discrepant
@GrantWinney: Actually, the conditional operator does not assign anything. The assignment operator is what assigns a value no matter what. The conditional operator *evaluates to a concrete value no matter what (i.e. not an abstract operational instruction such as "leave value unchanged").Discrepant
P
42

You can do:

someBool = (someStatement) ? true : someBool;

I don't think that gains you a lot of clarity over:

if (someStatement)
{
    someBool = true;
}

But it really seems to be a matter of taste. I wouldn't say either is clearly bad, but the former is uncommon, so I'd probably avoid it.


You ask why you can't use the operator like this:

someBool = (someStatement) ? true : ;

This would be a very big language change! Bear in mind that an assignment looks like this:

<location> = <expression>;

The expression is evaluated to give some value, and that value is stored in location. (Depending on whether location is a variable, property, field or indexing expression the "storing" operation could be quite different.)

Here you're proposing that the value of the expression on the right, in addition to its normal values, can be a "no-change" value, which has the special behaviour that when you use it in an assignment statement it causes no store operation to occur. That's different from any other normal value, and potentially surprising. But what would it mean if you used it in other places?

// Does this call DoSomething when cond is false?
// If so, what value is passed to it?
someObject.DoSomething(cond?x:);

// What happens here if cond is false? Does it cancel
// the entire assignment?
int x = 77 + (cond?2:) * 3 - 4;

// If cond is false, are methods F1 and F2 called or not called?
int x = F1() + (cond?2:) + F2();

// What does this do? Does it skip the return if cond is false?
return (cond?2:);

I think you'd find it extremely hard to come up with sensible, intuitive and consistent behaviour for the operator in all these circumstances, and I don't think it would be useful anywhere other than in a simple assignment. It just doesn't fit with the rest of the language - including it would make the language harder to learn, read, understand, implement and explain. It's just not worth it for a tiny bit of conciseness.

Precedent answered 24/7, 2014 at 13:53 Comment(4)
Great answer! Yeah, I hadn't even thought about how it would be implemented in the languageSetscrew
Is there anything wrong with doing a one-liner, i.e. if (someStatement) someBool = true; ?Laplante
I think @Chucky's answer is far betterJehovah
What does this do? Just throws compiler error. Don't see a problem here. Or for example takes the default value. I think it would be convenient to have such single argument ternary operator in some casesDynamometry
H
21

Basically, you're trying to use the conditional operator for something that it's not designed for.

It's not meant to optionally take some action... it's meant to evaluate one expression or another, and that be the result of the expression.

If you only want to perform an action when some condition is met, use an if statement - that's precisely what it's there for.

In your example, you could use:

// Renamed someStatement to someCondition for clarity
someBool |= someCondition;

or

someBool = someCondition ? true : someBool;

... in other words "use the existing value unless someCondition is true... but personally, I think the original if statement is clearer.

Hayashi answered 24/7, 2014 at 13:22 Comment(5)
bummer :/ I personally think that the conditional operator is more beautiful.Setscrew
@JohanHjalmarsson: See my edit for how you could use it - but really, it's meant to evaluate an expression. Remember that it's just an expression, not a statement.Hayashi
yeah, I know, the seccond option is what I use. Was just curious if there were some other way besides that and a normal if-statementSetscrew
@JohanHjalmarsson: Well you could write an extension method on bool, so that you could write someCondition.MaybeReplace(ref current, newValue). But that would be pretty hideous...Hayashi
That actually made me chuckle ^^ Hideous indeedSetscrew
B
4

Some background: we use constructs like this a lot:

sql = "SELECT x FROM table WHERE Y " + (condition ? " AND Column = 1" : "");

We also use constructs like this in Razor views

<div class='someclass @(condition ? "anotherclass" : "")'></div>

The : "" is pretty annoying so we built an extension method

public static T Then<T>(this bool value, T result)
{
    return value ? result : default(T);
}

Usage:

<div class='someclass @condition.Then("anotherclass")'></div>

taken from here

Bastogne answered 21/2, 2020 at 15:27 Comment(0)
C
0

Not the exact same example as the OP's so might not be valid to the specific question.

I might not have fully understood the question as it seems more complicated case than my simple use with colors.

But for my use case this solution worked.

Apologies if it does not solve the OP's specific use case.

My case was:

if ( a ) colorRed;

else if ( b ) colorBlue;

else // no color

[1]

I first tested:

( ( conditionA ) ? colorRed : ( conditionB ) ? colorBlue : false )

It throws this error:

Type of conditional expression cannot be determined because there is no implicit conversion between 'System.Windows.Media.Brush' and 'bool' CS0173 247 81

[2]

Testing then as suggested here: https://mcmap.net/q/237410/-operators-instead-of-if-else

( ( conditionA ) ? colorRed : ( conditionB ) ? colorBlue : () )

It throws these errors:

Invalid expression term ')' CS1525 247 97

) expected CS1026 247 100

[3]

Finally tested this:

( ( conditionA ) ? colorRed : ( conditionB ) ? colorBlue : null )

No error. With needed output.

[4]

But I found out the same output is obtained without null too for my use case after all.

( ( conditionA ) ? colorRed : colorBlue )

[3] might have some use to some scenarios when the else clause does make a difference in the output.

Creek answered 30/3 at 21:41 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.