Reputation: 1151
DateTime? date = null;
string tmp = "a" + "(" + date ?? "blablabla" + ")";
Console.WriteLine(tmp);
This will print something close to: 'a ('
.
Is this a bug with null-coalescing operator
?
If I put date ?? "blablabla"
in parenthesis, it is underlined as error.
Upvotes: 5
Views: 348
Reputation: 241789
First, you should always assume it's your fault, not the compiler's fault; select
isn't broken. Do you honestly think the Visual Studio 2010 implementation of the ??
operator hasn't been battle tested? When you encounter something that doesn't match your expectations, check your expectations. Get out the manual, and make sure that you understand exactly what is suppose to happen. In this case, open the language specification.
If you proceed to §1.4 of the specification, you'll see a table that groups operators into precedence groupings; you can also find it online. In particular, the null coalescing operator ??
is near the bottom, above only the lowly conditional ternary operator and assignments and =>
. It is below the additive operator. Thus, your statement
string tmp = "a" + "(" + date ?? "blablabla" + ")";
is treated by the compiler as
string tmp = (("a" + "(" + date) ?? ("blablabla" + ")"));
I'm not going to be completely pedantic and also parenthesize the first additive expression1. Since the left-hand-side of the expression in that statement is never null, of course it always assigns "a("
(or "a("
+ date.ToString()
when date.HasValue
is true) to tmp
.
The main point is that you had an incorrect expectation as to what should be happening that you should have verified against the manual.
If I put
date ?? "blablabla"
in parenthesis, it is underlined as error.
Of course it is. Did you even read the error message? It probably tells you that you can't do ??
on a DateTime?
and a string
because there are no implicit conversions between DateTime?
and string
in either direction. This, too, is covered in the language specification; see §7.13. You have to read this message and respond to it. To get something semantically equivalent to what you're trying to express, you'll have to resort to the conditional ternary operator:
date.HasValue ? date.ToString() : "blablabla"
and then wrap that whole thing in parentheses because the conditional ternary operator has very low precedence.
Finally, I find a correctly parenthesized version of your code rather ugly, not fun to read, and probably not enjoyable to maintain. Just make it simple, please:
var tmp = String.Format("a({0})",
date.HasValue ? date.ToString() : "blablabla");
Now it is so clear what is going on and what is going to happen. I don't have to think to understand it. Save your thinking for the difficult problems you'll encounter.
1: Be careful. We would need to add in a method call to date.ToString
(which has the highest precedence) before attempting to correctly figure out what is evaluated first.
Upvotes: 6
Reputation: 98868
From C# Language Specification §1.4
The following table summarizes C#’s operators, listing the operator categories in order of precedence from highest to lowest. Operators in the same category have equal precedence.
It says Additive operators is higher precedence than null coalescing operator.
So, +
has higher precedence than ??
and that's why "blablabla" + ")"
expression works first.
And since date
is null
, the statement works like;
string tmp = "a" + "(" + null;
And normally result will be a(
Upvotes: 1
Reputation: 20640
"blablabla"
is not a date, so you can't use is to set a date?
.
string tmp = "a" + "(" + date ?? "blablabla" + ")";
is equivalent to
string tmp = ("a" + "(" + date) ?? ("blablabla" + ")");
which is where your a(
is coming from.
However
string tmp = "a" + "(" + (date ?? DateTime.Now) + ")";
or similar should work.
Upvotes: 2
Reputation: 40756
Here just another version:
DateTime? date = null;
string tmp = string.Format("a({0})",
date.HasValue ? date.ToString() : "blablabla");
I really love string.Format
instead of concatenation.
Upvotes: 3
Reputation: 9800
Null-coalescing operator ??
has a lower precedence than the +
operator, so your code is equal to
string tmp = ("a" + "(" + date) ?? ("blablabla" + ")");
Since everything in the +
operation with a string produces a string (by calling .ToString()
on all non-string operands), your code will always produce the "a("
string.
Upvotes: 8
Reputation: 6864
It's not a bug with the null-coalescing operator.
It's operator precedence:
"a" + "(" + date ?? "blablabla" + ")"
is the same as:
("a" + "(" + date.ToString() ) ?? ( "blablabla" + ")" )
and ("a" + "(" + date.ToString() )
is not null.
Upvotes: 0
Reputation: 6193
This is most likely because date
isn't a string and the ??
operator can't determine a common base type for date
and "blablabla"
. Try (date.ToString() ?? "blablabla")
. But this won't satisfy your need either because date.ToString()
will never be null
.
string tmp = "a" + "(" + (date ?? DateTime.Now) + ")";
should work.
Upvotes: 0