Click here to Skip to main content
15,888,816 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have the following if() statement:

if( _hexColourString.Length >= 8 )
    _bytes[ 3 ] = byte.Parse( _hexColourString.Substring( start + 6, 2 ), NumberStyles.AllowHexSpecifier );
else
    _bytes[ 3 ] = 0x00;


If I try to express this using the ternary operator, I get an error saying I cannot implicitly convert an int to a byte. The following does NOT compile:

_bytes[ 3 ] = ( _hexColourString.Length >= 8 ) ? byte.Parse( _hexColourString.Substring( start + 6, 2 ), NumberStyles.AllowHexSpecifier ) : 0x00;


So I thought I'd check which half of the ternary assignment was giving the problem. I took out the conditional part of the statement and wrote the two assignments as separate statements, like this:

_bytes[ 3 ] = byte.Parse( _hexColourString.Substring( start + 6, 2 ), NumberStyles.AllowHexSpecifier );
_bytes[ 3 ] = 0x00;


Both of these compile. The ternary operator seems to be changing the implicit type of one of the assignments (the literal 0x00).

Why does the plain assignment _bytes[ 3 ] = 0x00; compile okay without a cast but requires one when the expression is part of a ternary operator?

What I have tried:

As a final sanity check, I wanted to see conclusively which side of the assignment was causing the problem. I suspected the literal hex byte and I appear to be correct. The following pointless statement compiles:

_bytes[ 3 ] = ( _hexColourString.Length >= 8 ) ? byte.Parse( _hexColourString.Substring( start + 6, 2 ), NumberStyles.AllowHexSpecifier ) :
                byte.Parse( _hexColourString.Substring( start + 6, 2 ), NumberStyles.AllowHexSpecifier );


But the following equally pointless statement does NOT compile:

_bytes[ 3 ] = ( _hexColourString.Length >= 8 ) ? 0x00 : 0x00;
Posted
Updated 28-Nov-18 2:04am
v2
Comments
CHill60 28-Nov-18 7:33am    
Because 0x00 is an int not a byte perhaps?
Patrick Skelton 28-Nov-18 7:37am    
Of course, you are correct. I guess my question should really have been why does the plain assignment (_bytes[ 3 ] = 0x00;) compile okay without a cast but requires one when the expression is part of a ternary operator?
CHill60 28-Nov-18 8:00am    
Normally I would say that there has been an implicit conversion, but there is no implicit conversion from int to byte. The compiler must be detecting that 0x00 as a constant is smaller than a byte and won't cause overflow - who knew MS could be that clever? :-)
Patrice T 28-Nov-18 7:38am    
And the compiler tells you something ?
Patrick Skelton 28-Nov-18 7:44am    
Sorry, I'm not sure I understand the question. When I use 0x00 in a ternary operator, the compiler does indeed tell me I cannot convert an int to a byte, which is an unambiguous, concise statement of the problem. I have attempted to clarify my question.

Try just "0"

_bytes[ 3 ] = ( _hexColourString.Length >= 8 ) ? byte.Parse( _hexColourString.Substring( start + 6, 2 ), NumberStyles.AllowHexSpecifier ) : 0;


Or an explicit cast

_bytes[ 3 ] = ( _hexColourString.Length >= 8 ) ? byte.Parse( _hexColourString.Substring( start + 6, 2 ), NumberStyles.AllowHexSpecifier ) : (byte)0;
 
Share this answer
 
Comments
Patrick Skelton 29-Nov-18 3:42am    
Your code fixes my problem but I have marked a different reply as solution because it offers an explanation, which should help anyone else who stumbles across this thread.

I will in fact probably use the explicit cast you mention above, just to tell anyone else reading my code that I have not made a mistake.
Quote:
I guess my question should really have been why does the plain assignment (_bytes[ 3 ] = 0x00;) compile okay without a cast but requires one when the expression is part of a ternary operator?

Because the compiler can tell from the context that the constant value should be a byte, not an int.
When you create a ternary operation though, the compiler has a choice:
C#
byte b = 100;
byte c = (a ? b : 0)
Could be seen in two ways:
C#
byte b = 100;
byte c = (a ? b : (byte) 0)
Or
C#
byte b = 100;
byte c = (a ? (int) b : 0)
And it will pick the second because integers are the more common and "natural" unit.

Then it complains because the implicit cast from a int to a byte needed could potentially throw away information. (Not that there is any to throw away, but hey - compiler writers can't think of everything!)
 
Share this answer
 
Comments
Patrick Skelton 29-Nov-18 3:38am    
An excellent explanation, sir! Thank you!
OriginalGriff 29-Nov-18 3:52am    
You're welcome!
In addition to the other two solutions (and comments) I found this quite good explanation from Eric Lippert ... Why do I have to typecast an int in a ternary expression?[^]
 
Share this answer
 
Comments
Patrick Skelton 29-Nov-18 3:50am    
That is indeed an excellent explanation, making good use of direct quotes from the language spec. Thank you!

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900