C# Compiler Bug?

G

Guest

In this case, I am trying to perfom a math function on a byte value with
another byte value returned by a function. There appears to be no way to
convince the compiler to do this even with explicit casts. Works fine if the
values being added are constants, but when one is a function it doesn't work
correctly.

Is this a compiler bug or am I missing something?

// VS 2003.net C# code
public class Class1
{
public Class1()
{
}
private byte ByteFunc()
{
return (byte)1;
}
public void MyFunc()
{
byte byOut;
byOut = 1; // OK: No error
byOut = 1*1; // OK: No error
byOut = (byte)1*(byte)2; // OK: No error


byOut = ByteFunc(); // OK: No error
byOut = ByteFunc() * 2; // ERROR: Cannot implicitly convert 'int'
to 'byte'
byOut = (byte)ByteFunc() * (byte)2; // ERROR: Cannot implicitly
convert 'int' to 'byte'
}
}
 
J

Jon Skeet [C# MVP]

dlf said:
In this case, I am trying to perfom a math function on a byte value with
another byte value returned by a function. There appears to be no way to
convince the compiler to do this even with explicit casts. Works fine if the
values being added are constants, but when one is a function it doesn't work
correctly.

Is this a compiler bug or am I missing something?

You're missing something, I'm afraid.
// VS 2003.net C# code
public class Class1
{
public Class1()
{
}
private byte ByteFunc()
{
return (byte)1;
}
public void MyFunc()
{
byte byOut;
byOut = 1; // OK: No error
byOut = 1*1; // OK: No error
byOut = (byte)1*(byte)2; // OK: No error

The compiler does all of the above at compile time, and can see that
the result is in the bounds of byte. (See section 13.1.6 of the ECMA
spec.)
byOut = ByteFunc(); // OK: No error

Yup, as you'd expect, no doubt.
byOut = ByteFunc() * 2; // ERROR: Cannot implicitly convert 'int'
to 'byte'
byOut = (byte)ByteFunc() * (byte)2; // ERROR: Cannot implicitly
convert 'int' to 'byte'

In both of these cases, the type of the expression (on the right hand
side of the assignment operator) is int, because there is actually no
operator *(byte, byte) - each operand gets converted to int and then
operator *(int, int) is used, which has a resulting type of int. (See
section 14.7.1 of the ECMA spec.)

What you need to do is cast the whole expression:

byOut = (byte) (ByteFunc()*2);
 
J

Jon Skeet [C# MVP]

José Joye said:
Try this:

byOut = Convert.ToByte(ByteFunc() * 2);

There's no need to call a method to do this - a straight cast will do
fine:

byOut = (byte) (ByteFunc()*2);

The important thing is to make sure that it's the whole expression
which is cast, not just the result of ByteFunc() (which is already a
byte).
 
S

Shiva

Hi,
Cast the whole expression to byte: byOut = (byte)(ByteFunc() * 2);

In this case, I am trying to perfom a math function on a byte value with
another byte value returned by a function. There appears to be no way to
convince the compiler to do this even with explicit casts. Works fine if the
values being added are constants, but when one is a function it doesn't work
correctly.

Is this a compiler bug or am I missing something?

// VS 2003.net C# code
public class Class1
{
public Class1()
{
}
private byte ByteFunc()
{
return (byte)1;
}
public void MyFunc()
{
byte byOut;
byOut = 1; // OK: No error
byOut = 1*1; // OK: No error
byOut = (byte)1*(byte)2; // OK: No error


byOut = ByteFunc(); // OK: No error
byOut = ByteFunc() * 2; // ERROR: Cannot implicitly convert 'int'
to 'byte'
byOut = (byte)ByteFunc() * (byte)2; // ERROR: Cannot implicitly
convert 'int' to 'byte'
}
}
 
J

José Joye

I agree :).
However, I'm now wondering why we have such a method available:
Convert.ToByte(int).

José
José Joye said:
Try this:

byOut = Convert.ToByte(ByteFunc() * 2);

There's no need to call a method to do this - a straight cast will do
fine:

byOut = (byte) (ByteFunc()*2);

The important thing is to make sure that it's the whole expression
which is cast, not just the result of ByteFunc() (which is already a
byte).
 
G

Guest

Thanks, this works, but I'm not sure why a byte * byte ends up to be a type
that need to be converted to byte. Seems to me that in other typed languages
that I have used, since all types are the same this woule be impict. So
whats up here? Is the return of the function coming back int even though it
is declared byte?

Darren
 
J

Jon Skeet [C# MVP]

dlf said:
Thanks, this works, but I'm not sure why a byte * byte ends up to be a type
that need to be converted to byte. Seems to me that in other typed languages
that I have used, since all types are the same this woule be impict. So
whats up here? Is the return of the function coming back int even though it
is declared byte?

No, it's the multiplication that is coming back as int. Java works the
same way, btw.
 
J

Jon Skeet [C# MVP]

José Joye said:
I agree :).
However, I'm now wondering why we have such a method available:
Convert.ToByte(int).

Well, they work slightly differently - in an unchecked context,
(byte)256 results in 0; Convert.ToByte will *always* throw an
OverflowException.

I suspect it also makes it easier in some cases for autogeneration of
code and possibly some reflection stuff.
 
G

Guest

Why are you using bytes, is it because you *actually* need a number of that
many bits, or is it because the limits for the number you are using *just
happens* to marry up to the numerical limits of a byte? If the former, then
perhaps there shouldn't be a reason why you'd want to multiply it by another
byte?
 
S

Stoitcho Goutsev \(100\) [C# MVP]

Hi dlf,

As Jon said the multiplication is the reason of your confusion.
When you multiply two bytes the result cannot fit in a byte in all some of
the cases. What if you multiplay 255*255. That's why the result of
multiplication is *int*.
There couldn't be conversion from *int* to *byte*. Any alnguage is going to
at least warn you if you try to do this implicitly
 
J

Jon Skeet [C# MVP]

Stoitcho Goutsev (100) said:
As Jon said the multiplication is the reason of your confusion.
When you multiply two bytes the result cannot fit in a byte in all some of
the cases. What if you multiplay 255*255. That's why the result of
multiplication is *int*.

I've never bought that as an explanation, to be honest - it doesn't
explain why int*int doesn't result in a long, and why long*long isn't
banned entirely.

I suspect the reason is much more performance-based - it's cheaper to
convert bytes to ints and do an int*int multiplication than a real
byte*byte multiplication on most modern processors, I guess.
 
J

Jay B. Harlow [MVP - Outlook]

Stoitcho,
Any alnguage is going to
at least warn you if you try to do this implicitly
VB.NET knows that both arguments are bytes & returns a byte from the
expression. Just as an expression with 2 ints return an int.

At run time if the value does not fit in a Byte VB.NET will throw an
OverflowException. Looking at the IL that VB.NET creates it does the
expression as an Integer, then uses conv.ovf.u1 to convert the result back
to a Byte.

Try the following in VB.NET:

Dim b1, b2, b3 As Byte
b1 = 255
b2 = 255
b3 = b1 * b2

Hope this helps
Jay

Stoitcho Goutsev (100) said:
Hi dlf,

As Jon said the multiplication is the reason of your confusion.
When you multiply two bytes the result cannot fit in a byte in all some of
the cases. What if you multiplay 255*255. That's why the result of
multiplication is *int*.
There couldn't be conversion from *int* to *byte*. Any alnguage is going to
at least warn you if you try to do this implicitly

--

Stoitcho Goutsev (100) [C# MVP]


dlf said:
Thanks, this works, but I'm not sure why a byte * byte ends up to be a type
that need to be converted to byte. Seems to me that in other typed languages
that I have used, since all types are the same this woule be impict. So
whats up here? Is the return of the function coming back int even
though
it
is declared byte?

Darren
way
fine
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top