I was using the ||= operator in Ruby on Rails and I saw that C# have something similar.
Is ||= in Ruby on Rails equals to ?? in C# ?
What is the difference if there is one?
Based on what I have read here, the x ||= y operator works like:
This is saying, set x to y if x is nil, false, or undefined. Otherwise set it to x.
(modified, generalized, formatting added)
The null-coalescing operator ?? on the other hand is defined like:
The ?? operator is called the null-coalescing operator. It returns the left-hand operand if the operand is not null; otherwise it returns the right hand operand.
(formatting added)
Based on that there are two important differences:
The ?? does not assign, it is like a ternary operator. The outcome can be assigned, but other things can be done with it: assign it to another variable for instance, or call a method on it; and
The ?? only checks for null (and for instance not for false), whereas ||= works with nil, false and undefined.
But I agree they have some "similar purpose" although || in Ruby is probably more similar with ??, but it still violates (2).
Also mind that the left part of the null-coalescing operator does not have to be a variable: on could write:
Foo() ?? 0
So here we call a Foo method.
Simple answer... yes and no.
The purpose of the ||= operator in Ruby-on-Rails is to assign the left-hand operand to itself if not null, otherwise set it to the the right-hand operand.
In C#, the null coalescing operator ?? makes the same check that ||= does, however it's not used to assign. It serves the same purpose as a != null ? a : b.
Related
var a = b?.c.d;
Shouldn't this expression always give a compile error? If b is null, the null value is propagated through so c will also be null and thus also need this operator. In my understanding usage of this operator in an expression spreads viral.
But neither Visual Studio 2015 nor Resharper says anything to me, am I missing something here?
The operator is just syntactic sugar for this:
MyType a = b == null ?
null:
b.c.d;
Why this should throw a compile-error is unclear to me.
If b is null, the null value is propagated through so c will also be null and thus also need this operator
This isn´t true. Actually when b is null c doesn´t even exist as there´s no instance on which that member could exist. So in short the operator just returns null and omits evaluating c or even d any further.
This operator does short circuit and returns null in case of b is null.
var a = b == null ? null : b.c.d
This is what that statement would look like in the old way, the ?. operator doesn't look deeper when what is before it is null, it just returns null, you WILL however get an error where b is defined but b.c == null since you didn't write as var a = b?.c?.d.
Note that:
var a1 = b?.c.d;
is entirely different from:
var a2 = (b?.c).d;
It is not very easy to explain in short how the unary operator ?. works (yes, unary!). But the idea is that the rest of the "chain" of "operations" is skipped if the expression before ?. is null.
So for a1, you get a null of the compile-time type carried by member d (or Nullable<> of that type if necessary) whenever b happens to be null. When b happens to be non-null, you get the same as b.c.d which may fail if b.c is null.
But a2 is quite different. It will always blow up if b is null, because then the parenthesis (b?.c) will be a null reference, and the next . operator will lead to NullReferenceException. (I am assuming here that c has a reference-type at compile-time.)
So do not think there is a kind of "left-associativity" that makes b?.c.d equivalent to (b?.c).d!
You can find a link to the preliminary C# Language Specification in this answer in another thread; they mention Null-conditional operator as an unary operator in § 7.7.1.
Hey Everyone I thought that this code would be valid in any case because it is casted to bool
parameter.Request?.InnerData?.Any() == false
Instead this code is casted to type bool?
Can tell me someone why? (this is main question)
Is there better way to check this instead of something like this?
var isThereInnerData = parameter.Request?.InnerData?.Any();
if (isThereSegments == null || isThereSegments == false)
With a null-conditional operator, null propagates. You can't end up with a non-nullable type if you use the null-conditional operator - this is the same behaviour in languages where null operations are "safe" by default (SQL, Objective-C, ...). So the result is default(bool?) if parameter.Request is null, or parameter.Request.InnerData is null. Otherwise, you get true or false, but by using the null-conditional operator you already assume the result can in fact be null, so the compiler must accomodate that. Since bool can't be null, it is changed into a nullable bool (bool?).
The solution is simple - think about what logical value a null should have, and use that:
if (parameter.Request?.InnerData?.Any() ?? true)
In this case, a null value is interpreted as true, but you can also use false if you want. Alternatively, instead of the null-coalescing operator, you can use GetValueOrDefault, whatever feels better for you.
Here is what C# reference says about ?. operator:
x?.y – null conditional member access. Returns null if the left hand
operand is null.
Since at compile time the compiler doesn't knows whether the expression will evaluate to a non-null value, the compiler infers the type as Nullable<bool>
Since you are chaining the ?. operator this line from msdn documentation is relevant too:
The null-condition operators are
short-circuiting. If one operation in a chain of conditional member
access and index operation returns null, then the rest of the chain’s
execution stops. Other operations with lower precedence in the
expression continue. For example, E in the following always executes,
and the ?? and == operations execute.
bool is a value type and per default cannot be compared with null. C# converts your return value to bool? to give you the option to support both.
why can't I have something like:
Some_Function ? myList.Add(a) : throw new Exception();
Why can't I throw exception in else part of ?: operator? what is the main purpose of ?: operator?
Suggestion
If anybody else wondered about the same thing, beside reading the answers below, i suggest that you read this post as well..
Expression Versus Statement
The other answers and comments are of course true (we can refer to the documentation), though my understanding of the question is more like, "why does it have to be that way?".
According to the C# 5.0 specification, the conditional operator forms an expression, not a statement. I suspect that the reason why it's not a statement, thus preventing you from doing something like a ? b() : throw e is simply because we already have a statement construct for achieving basically the same thing; namely, if..else.
if (a) { b(); } else { throw e; }
The benefit of the conditional operator is that it can be used within statements or other expressions.
bool? nb = GetValue();
if (nb ?? (a ? b() : c())) { throw e; }
Because it is defined as:
null-coalescing-expression ? expression : expression
As you can read in ?: Operator (C# Reference):
The conditional operator (?:) returns one of two values depending on the value of a Boolean expression.
One of both expression is evaluated depending on the boolean value of null-coalescing-expression.
Since neither of your two code fragments are expressions that evaluate to a value (List.Add() is void and an exception doesn't evaluate to a value either), this can't compile.
You need to remember that Ternary operator must return something and List.Add is a void method so it fails. Both the sides must be compatible and should return something.
The MSDN says:
The condition must evaluate to true or false. If condition is true,
first_expression is evaluated and becomes the result. If condition is
false, second_expression is evaluated and becomes the result.
And myList.Add(a) is not an expression.
See ?: Operator on MSDN. Its clearly explained there.
The conditional operator (?:) returns one of two values depending on the value of a Boolean expression. Following is the syntax for the conditional operator.
condition ? first_expression : second_expression;
The condition must evaluate to true or false. If condition is true, first_expression is evaluated and becomes the result. If condition is false, second_expression is evaluated and becomes the result. Only one of the two expressions is evaluated.
Either the type of first_expression and second_expression must be the same, or an implicit conversion must exist from one type to the other.
You can express calculations that might otherwise require an if-else construction more concisely by using the conditional operator. For example, the following code uses first an if statement and then a conditional operator to classify an integer as positive or negative.
The conditional operator (?:) returns one of two values depending on the value of a Boolean expression. Following is the syntax for the conditional operator.
The condition must evaluate to true or false. If condition is true, first_expression is evaluated and becomes the result. If condition is false, second_expression is evaluated and becomes the result. Only one of the two expressions is evaluated.
Either the type of first_expression and second_expression must be the same, or an implicit conversion must exist from one type to the other.
You can express calculations that might otherwise require an if-else construction more concisely by using the conditional operator. For example, the following code uses first an if statement and then a conditional operator to classify an integer as positive or negative.
For example, given this code:
int? ReallyComplexFunction()
{
return 2; // Imagine this did something that took a while
}
void Something()
{
int i = ReallyCleverFunction() ?? 42;
}
... is it guaranteed that the function will only be called once? In my test it's only called once, but I can't see any documentation stating I can rely on that always being the case.
Edit
I can guess how it is implemented, but c'mon: we're developers. We shouldn't be muddling through on guesses and assumptions. For example, will all future implementations be the same? Will another platform's implementation of the language be the same? That depends on the specifications of the language and what guarantees it offers. For example, a future or different platform implementation (not a good one, but it's possible) may do this in the ?? implementation:
return ReallyComplexFunction() == null ? 42 : ReallyComplexFunction();
That, would call the ReallyComplexFunction twice if it didn't return null. (although this looks a ridiculous implementation, if you replace the function with a nullable variable it looks quite reasonable: return a == null ? 42 : a)
As stated above, I know in my test it's only called once, but my question is does the C# Specification guarantee/specify that the left-hand side will only be called once? If so, where? I can't see any such mention in the C# Language Specification for ?? operator (where I originally looked for the answer to my query).
The ?? operator will evaluate the left side once, and the right side zero or once, depending on the result of the left side.
Your code
int i = ReallyCleverFunction() ?? 42;
Is equivalent to (and this is actually very close to what the compiler actually generates):
int? temp = ReallyCleverFunction();
int i = temp.HasValue ? temp.Value : 42;
Or more simply:
int i = ReallyCleverFunction().GetValueOrDefault(42);
Either way you look at it, ReallyCleverFunction is only called once.
The ?? operator has nothing to do with the left hand. The left hand is run first and then the ?? operator evaluates its response.
In your code, ReallyCleverFunction will only run once.
It will be only called once. If the value of ReallyCleverFunction is null, the value 42 is used, otherwise the returned value of ReallyCleverFunction is used.
It will evaluate the function, then evaluate the left value (which is the result of the function) of the ?? operator. There is no reason it would call the function twice.
It is called once and following the documentation I believe this should be sufficient to assume it is only called once:
It returns the left-hand operand if the operand is not null; otherwise
it returns the right operand.
?? operator
It will only be run once because the ?? operator is just a shortcut.
Your line
int i = ReallyCleverFunction() ?? 42;
is the same as
int? temp = ReallyCleverFunction();
int i;
if (temp != null)
{
i = temp.Value;
} else {
i = 42;
}
The compiler does the hard work.
Firstly, the answer is yes it does guarantee it will only evaluate it once, by inference in section 7.13 of the official C# language specification.
Section 7.13 always treats a as an object, therefore it must only take the return of a function and use that in the processing. It says the following about the ?? operator (emphasis added):
• If b is a dynamic expression, the result type is dynamic. At run-time, a is first evaluated. If a is not null, a is converted to dynamic, and this becomes the result. Otherwise, b is evaluated, and this becomes the result.
• Otherwise, if A exists and is a nullable type and an implicit conversion exists from b to A0, the result type is A0. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0, and this becomes the result. Otherwise, b is evaluated and converted to type A0, and this becomes the result.
• Otherwise, if A exists and an implicit conversion exists from b to A, the result type is A. At run-time, a is first evaluated. If a is not null, a becomes the result. Otherwise, b is evaluated and converted to type A, and this becomes the result.
• Otherwise, if b has a type B and an implicit conversion exists from a to B, the result type is B. At run-time, a is first evaluated. If a is not null, a is unwrapped to type A0 (if A exists and is nullable) and converted to type B, and this becomes the result. Otherwise, b is evaluated and becomes the result.
As a side-note the link given at the end of the question is not the C# language specification despite it's first ranking in a Google Search for the "C# language specification".
In this .NET code:
return Redirect("~/Home" ?? "JaneDoe");
If I'm reading the docs right, the "??" operator appears to operate similarly to IsNull in SQL:
IsNull("~/Home", "JaneDoe")
"~Home" and "JaneDoe" are simply strings, right? There's no condition in the return Redirect code where "JaneDoe" will be what's passed into "Redirect", is there? I'm not sure what to make of this snippet, I can only presume it's a placeholder for something to come later.
This code is from a .NET-MVC project in development, part of a .cs file that is a LoginController.
Yes, this is just bad code. That will always be equivalent to
return Redirect("~/Home");
I'm slightly surprised the compiler isn't smart enough to give a warning about it, to be honest. It would be nice if it could tell that a constant non-null expression was being used on the LHS of the null-coalescing operator.
The ?? operator is called the null-coalescing operator and is used to define a default value for a nullable value types as well as reference types. It returns the left-hand operand if it is not null; otherwise it returns the right operand.
In your case, it will never return JaneDoe
Yes, you're reading it correctly. That will always return "~/Home", presumably it was planned to change it to a variable at some point.
This would always use the "~/Home" string. The null-coalescing operator (??) selects the left side if it is non-null, or the right side if it is null.
Correct, the expression will never return "JaneDoe".