Click here to Skip to main content
15,902,198 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.

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!
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!
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.

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