Subject: Restore your thinning hair back to normal

From: Women's Magazine <[email-masked]>
Date: Thu, 14 Aug 2014 06:03:53 -0700

[Woman's Day Magazine]

Expert-Q and A: Fighting Hair Loss in Women
--------------------------------------------------------
Unexplained, excessive hair loss can be worrying and scary. The good news is, there's a way to fix and treat your hair issues.

>> http://www.iffgot.com/cdc-org/women_hair_loss/res/

Hair is probably a woman's most important feature. Signs of thinning hair can take the sail out of almost any woman's day.

Many women with hair loss suffer in silence, altering their hairstyle to hide thinning or patches. But the sooner you seek care, the better the chances of successfully treating it.

>> http://www.iffgot.com/cdc-org/women_hair_loss/res/

Magazine | Science | Health + Wellness | OWN Women's Day::
[PO-Box 128 |Oceana| |WV| |24870-0128| [Message/exit settings http://www.iffgot.com/A/]

The American Hair Loss Association recognizes that hair loss is women is a serious life altering condition that can no longer be ignored by the medical community and society as a whole.

This works:

short value;
value = 10 > 4 ? 5 : 10;
This works:

short value;
value = "test" == "test" ? 5 : 10;
This doesn't work:

short value;
string str = "test";
value = "test" == str ? 5 : 10;
Neither does this:

short value;
string str = "test";
value = "test".Equals(str) ? 5 : 10;
The last two cases I am getting the following error:

Cannot implicitly convert type 'int' to 'short'.
An explicit conversion exists (are you missing a cast?)
Why do I have to cast on the last two cases and not on the two first cases?

c# .net
share|improve this question
edited Aug 1 at 14:42

Groo
19.6k73690	
asked Aug 1 at 14:38

Vitor Freitas
370414
  	 	
@Tyler: indeed, sorry removed the close vote. The duplicate one I gave was not specific. stackoverflow.com/questions/3678792/ States the difference between compile-time (==) and run-time (equals). Also 10 > 4 will be optimized out by the compiler where a variable is most of the time checked run-time (of not a constant)   RvdK Aug 1 at 14:51
1	 	
possible duplicate of No implicit int -> short conversion in ternary statement   ahruss Aug 1 at 15:21
add a comment
4 Answers
activeoldestvotes
up vote
41
down vote
accepted
short value;
value = 10 > 4 ? 5 : 10;             //1
value = "test" == "test" ? 5 : 10;   //2
string str = "test";
value = "test" == str ? 5 : 10;      //3
value = "test".Equals(str) ? 5 : 10; //4
The last two ternary expressions (3,4) cannot be resolved to a constant at compile time. Thus the compiler treats the 5 and 10 as int literals, and the type of the entire ternary expression is int. To convert from an int to a short requires an explicit cast.

The first two ternary expressions (1,2) can be resolved to a constant at compile time. The constant value is an int, but the compiler knows it fits in a short, and thus does not require any casting.

For fun, try this:

value = "test" == "test" ? 5 : (int)short.MaxValue + 1;
share|improve this answer
edited Aug 1 at 14:49

answered Aug 1 at 14:44

Timothy Shields
17.8k22563
4	 	
finally a correct answer   Selman22 Aug 1 at 14:45
4	 	
For reference: this behavior implemented by the compiler is called Constant Folding   Bas Brekelmans Aug 1 at 14:48 
1	 	
@Groo -- You know it took less than 10 mins for the correct answer.   Hogan Aug 1 at 14:50
1	 	
Here's the MS Documentation that says this can happen. "A constant expression of type int can be converted to sbyte, byte, short, ushort, uint, or ulong, provided the value of the constant expression is within the range of the destination type." But this doesn't really explain why the compiler can't figure out that both 5 and 10 can be shorts, other than the obvious "because it can't".   ahruss Aug 1 at 15:04
  	 	
@ahruss The compiler absolutely can figure out that both 5 and 10 can be short. The problem is, if E is the expression B ? X : Y where B is a non-constant bool expression, then E is always interpreted as a non-constant expression, regardless of whether X and Y are constant or not. If X is 5 and Y is 10, the types of those expressions are both int. So E is non-constant and has type int. A non-constant int cannot be implicitly cast to a short.   Timothy Shields Aug 1 at 15:26 
show 5 more comments

up vote
4
down vote
You need a cast to make the two last examples work

value = (short)("test" == str ? 5 : 10);
Why dont't you need it in the first two?

Because the first two are compile-time constants. The compiler is able to translate 10 > 4 ? 5 : 10 to true ? 5 : 10, then to just 5

So when you write

value = 10 > 4 ? 5 : 10;
It's effectively the same as

value = 5;
which compiles because the compiler is allowed to implicitly cast constants if they are in the allowed range.

Conversely, "test" == str ? 5 : 10; is not a compile time constant, so the compile is not allowed to implcitly cast it. You need to make an explicit cast yoursef.

share|improve this answer
answered Aug 1 at 14:49

Falanwe
2,268924
1	 	
Entirely correct. For an "academic" difference between (short)("test" == str ? 5 : 10) and "test" == str ? (short)5 : (short)10, see my answer.   Jeppe Stig Nielsen Aug 4 at 0:48
add a comment
up vote
3
down vote
This is defined by the C# Language Specification, of course.

The key thing to be aware of is that there are two kinds of conversions from int to short. One is an explicit conversion which always applies but which requires you to write (short) explicitly before the int expression. The other one is an implicit constant expression conversion which only applies when (a) the int expression is a compile-time constant and (b) the value of this compile-time expression is within the range of a short, that is -32768 through 32767.

A literal like 5, 10 or 4 has type int in C# (that goes for any integer literal which is between -2147483648 and 2147483647 and not followed by a symbol L, U or similar). So if we look at the right-hand sides of all your assignments, they are clearly int expressions, not short.

In the case 10 > 4 ? 5 : 10, since 10 and 4 are compile-time constants, this is the same as true ? 5 : 10 because the > operator between ints is built-in and will result in a constant when the operands are constants. And in the same way true ? 5 : 10 gives 5 because all three operands are constants, and ?: is classified a constant itself in that case. So it really says:

short value = 5;
where the "5" is a compile-time constant. Hence it is checked at compile-time if the int 5 is within the range (it does not matter with the 10, it could be 999999), and since that is the case, the implicit constant expression conversion applies, and it is legal.

Note that you can do the same with:

const int huge = 10;
const int tiny = 4;
const int significant = 5;
const int unimporatnt = 10;
short value;
value = huge > tiny ? significant : unimportant;
as long as all the operands are const variables (pun?).

Now, if I managed to make the explanation clear, you will also know by now that the obstacle preventing value = "test" == str ? 5 : 10; from working is that you did not mark the str local as const. Do that, and it will be allowed.

With the Equals call, things are a bit worse. The result of a call to Equals is never considered a compile-time constant (and I don't think it is "optimized" away, for example "same".Equals("same") will actually call the method at run-time). Same thing would happen with (10).Equals(4) or (10).CompareTo(4) > 0 and so on, so strings are not special in this respect.

Most likely you know already that when

short value = cond ? 5 : 10;
is not allowed because cond is not a compile-time constant, you just use the explicit conversion instead, so write:

short value = cond ? (short)5 : (short)10;
or:

short value = (short)(cond ? 5 : 10);
Technically, they are not identical, since the first one has no narrowing conversion at run-time (the expressions (short)5 and (short)10 are literals of type short), while the last one has to convert an int to short at run-time (which is of course er than incredibly ).

The other (non-deleted) answers are correct, this is just bonus information.

share|improve this answer
answered Aug 4 at 0:45

Jeppe Stig Nielsen
18k22756
add a comment
up vote
2
down vote
The thing is that 10 > 4 ? 5 : 10; is actually converted to a constant at compile time before any type casting is needed. Meaning the compiler realized that the turnary statement can actually be reduced to a constant even before any implicit type casting is required for the compilation. So in other words that expression is the same as:

value = 5;
In the last two statements, that is not true since you are using a variable to hold the values for you and not a constant. The compiler doesn't check the actual value of the variable to see if it can reduce the expression to a constant. So you actually need the casting.