kul_mi
kul_mi

Reputation: 1151

Is this a bug in Visual Studio 2010 compiler?

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

Answers (7)

jason
jason

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

Soner Gönül
Soner Gönül

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

Matthew Strawbridge
Matthew Strawbridge

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

Uwe Keim
Uwe Keim

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

AgentFire
AgentFire

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

Grhm
Grhm

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

fero
fero

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

Related Questions