views:

67

answers:

3

I'm looking at some code golf in LINQPad and wondering why:

int c;
string o;

o+=c;//this works

o+=P==2?"."+c:c;//this doesn't

o+=P==2?"."+c:""+c;//this does

mostly why the first one works and the second one throws a "no implicit conversion between 'string' and 'int'" error.

+2  A: 

Your second, non-working example has inconsistent types in the ?: operator. What you have is:

o += (P == 2 ? (string) "." + c : (int) c);

(The types in parentheses above are there to clarify what the existing types are, not to cast them to a different type.)

Both sides of the : in the ternary operator must be of the same type. For this reason, your second example is a syntax error. The third example works, because concatenating with an empty string coerces c into a string.

JSBangs
Ahh, thanks. I didn't realize both sides had to be the same type. that makes sense though. I can't accept an answer yet, wait a few min.
182764125216
It's not quite as strict as you say. There must be a conversion from either the consequence to the type of the alternative, or from the alternative to the type of the consequence. (But, if they differ, not both.) The behaviour here is subtle; for some of those subtleties see my articles on the subject: http://blogs.msdn.com/b/ericlippert/archive/tags/conditional+operator/
Eric Lippert
+4  A: 

The + operator on strings can accept an int, resulting in another string. However, there is no implicit (or explicit) cast from int to string.

When you use the ternary operator ?:, both "branches" need to either be the same type, or the type of one has to be implicitly convertible to the other.

In your second example, the first branch is a string, after the + operator is done, but the second is just an int, so it doesn't work. In your third example, both branches are strings, so it's fine.

mquander
So to get your second answer to work enter: o+=P==2?"."+c:c.ToString();
Rudu
+2  A: 

The += operator uses the + operator, so the first is really:

o = o + c;

What the compiler actually creates is:

o = String.Concat((object)o, (object)c);

The integer is boxed, and the Concat method that takes object parameters is called. The ToString method will be called on both parameters to get their string values, and they are concatenated.

If you first convert the integer to a string, the code gets more straight forward:

o += c.ToString();

which becomes:

o = String.Concat(o, c.ToString());

In the second code, the types in the conditional operator doesn't match:

bool ? string : int

The second and third operand has to have the same type, like in the third code:

bool ? string : string

The second code really becomes:

o = String.Concat(
  o,
  P == 2
    ? String.Concat((object)".", (object)c)
    : c
);

and the third code really becomes:

o = String.Concat(
  o,
  P == 2
    ? String.Concat((object)".", (object)c)
    : String.Concat((object)String.Empty, (object)c)
);

Anyhow, you should consider using a StringBuilder to build strings instead of using the += operator:

StringBuilder builder = new StringBuilder;

if (P == 2) {
  builder.Append('.');
}
builder.Append(c);
Guffa
its in some code golf, so the goal is make it work with the fewest characters possible. I am aware its not the most efficient at runtime.
182764125216