A simple question about foreach and datatypes

T

Tony Johansson

Hello!

Why does not this cause a compile error because a ulong has never been
implicitly convertible to byte?

ulong[] vektor = {100000,200000,300000};
foreach(byte b in vektor)
{
Console.WriteLine("i={0}", b);
}

If I have these statements below then I get a compile error.
But it's almost the same as above. Is a bug perhaps?

ulong a = 1;
byte b;
b = a; // Here a ulong is not implicitly convertible to a byte so we get a
compile error which is correct

//Tony
 
R

Rene

Your foreach loop instructions are basically translated by the C# compiler
into a bunch of other instructions that are understood by the CLR.

One of the instructions that is emitted on your behalf is an instruction to
convert ulong to a byte without throwing an overflow error.

If you are not ok with this behavior you can change it in code by adding the
check using word:

checked
{
ulong[] vektor = { 100000, 200000, 300000 };
foreach (byte b in vektor)
{
Console.WriteLine("i={0}", b);
}
}
 
T

Tony Johansson

Hello!

Why does not this generate a compile error?
That's my question.
What is the reason for the compiler to accept this type of conversion.

//Tony

Rene said:
Your foreach loop instructions are basically translated by the C# compiler
into a bunch of other instructions that are understood by the CLR.

One of the instructions that is emitted on your behalf is an instruction
to convert ulong to a byte without throwing an overflow error.

If you are not ok with this behavior you can change it in code by adding
the check using word:

checked
{
ulong[] vektor = { 100000, 200000, 300000 };
foreach (byte b in vektor)
{
Console.WriteLine("i={0}", b);
}
}


Tony Johansson said:
Hello!

Why does not this cause a compile error because a ulong has never been
implicitly convertible to byte?

ulong[] vektor = {100000,200000,300000};
foreach(byte b in vektor)
{
Console.WriteLine("i={0}", b);
}

If I have these statements below then I get a compile error.
But it's almost the same as above. Is a bug perhaps?

ulong a = 1;
byte b;
b = a; // Here a ulong is not implicitly convertible to a byte so we get
a
compile error which is correct

//Tony
 
J

jehugaleahsa

As was explained before, the foreach loop is translated into this
(something like it):

using (IEnumerator enumerator = vektor.GetEnumerator())
{
while (enumerator.MoveNext())
{
byte b = (byte)enumerator.Current;
Console.WriteLine("i={0}", b);
}
}

There is an explicit (not implicit) cast that will succeed in your
case. However, the error, if there is one, will only occur at runtime.

The reason it succeeds in the generated code and not your code is that
the compiler puts some extra care into it to make sure it does
compile. Your example does not provide an explicit cast, while the
generated version does.

While I cannot send you the exact generated code (it is in MSIL), just
know that it does something similar to my example.
 
R

Rene

Why does not this generate a compile error?
That's my question.

For the same reason code below does not generate an error.

ulong a = 1;
byte b;
b = Convert.ToByte(a);

There is nothing wrong with code above, in that snippet, you are stating
that you want to convert a ulong to a byte and not to trhow an error if the
conversion overflows. why would the compiler throw a compile error here??

Like I said before, internally, the C# compiler is taking your foreach code
and creating code that the CLR can understand, **this icludes** generating
code that is doing the **convertion without trhouwing an error**, something
similar to the example avobe.

What is the reason for the compiler to accept this type of conversion.
Ah, because when you do a foreach loop internally you are calling the
GetEnumerator() function wich in turn return an IEnumerator that in turn
returns objects as it collection member, so there is no way to do a compile
time check because the compiler does not whats inside the object. You can
check the definition of the IEnumerator for more info.

If you want to loop throw an array and have the compile time check then do a
"for" loop.

ulong[] vektor = { 100000, 200000, 300000 };
for (int i = 0; i < vektor.Length; i++)
{
byte b = vektor;
Console.WriteLine("i={0}", b);
}




//Tony

Rene said:
Your foreach loop instructions are basically translated by the C#
compiler into a bunch of other instructions that are understood by the
CLR.

One of the instructions that is emitted on your behalf is an instruction
to convert ulong to a byte without throwing an overflow error.

If you are not ok with this behavior you can change it in code by adding
the check using word:

checked
{
ulong[] vektor = { 100000, 200000, 300000 };
foreach (byte b in vektor)
{
Console.WriteLine("i={0}", b);
}
}


Tony Johansson said:
Hello!

Why does not this cause a compile error because a ulong has never been
implicitly convertible to byte?

ulong[] vektor = {100000,200000,300000};
foreach(byte b in vektor)
{
Console.WriteLine("i={0}", b);
}

If I have these statements below then I get a compile error.
But it's almost the same as above. Is a bug perhaps?

ulong a = 1;
byte b;
b = a; // Here a ulong is not implicitly convertible to a byte so we get
a
compile error which is correct

//Tony
 
T

Tony Johansson

Hello!!

I understand what you mean but I would be more happy if this would cause a
compile error.
I think that the compiler is doing a bad job hiding an important error when
using byte for an ulong.

There is certainly a good reson for why the compiler is doing a thing that
may seems bad.


//Tony
 
T

Tony Johansson

Hello!

Good explained thanks!

//Tony

Rene said:
Why does not this generate a compile error?
That's my question.

For the same reason code below does not generate an error.

ulong a = 1;
byte b;
b = Convert.ToByte(a);

There is nothing wrong with code above, in that snippet, you are stating
that you want to convert a ulong to a byte and not to trhow an error if
the conversion overflows. why would the compiler throw a compile error
here??

Like I said before, internally, the C# compiler is taking your foreach
code and creating code that the CLR can understand, **this icludes**
generating code that is doing the **convertion without trhouwing an
error**, something similar to the example avobe.

What is the reason for the compiler to accept this type of conversion.
Ah, because when you do a foreach loop internally you are calling the
GetEnumerator() function wich in turn return an IEnumerator that in turn
returns objects as it collection member, so there is no way to do a
compile time check because the compiler does not whats inside the object.
You can check the definition of the IEnumerator for more info.

If you want to loop throw an array and have the compile time check then do
a "for" loop.

ulong[] vektor = { 100000, 200000, 300000 };
for (int i = 0; i < vektor.Length; i++)
{
byte b = vektor;
Console.WriteLine("i={0}", b);
}




//Tony

Rene said:
Your foreach loop instructions are basically translated by the C#
compiler into a bunch of other instructions that are understood by the
CLR.

One of the instructions that is emitted on your behalf is an instruction
to convert ulong to a byte without throwing an overflow error.

If you are not ok with this behavior you can change it in code by adding
the check using word:

checked
{
ulong[] vektor = { 100000, 200000, 300000 };
foreach (byte b in vektor)
{
Console.WriteLine("i={0}", b);
}
}


Hello!

Why does not this cause a compile error because a ulong has never been
implicitly convertible to byte?

ulong[] vektor = {100000,200000,300000};
foreach(byte b in vektor)
{
Console.WriteLine("i={0}", b);
}

If I have these statements below then I get a compile error.
But it's almost the same as above. Is a bug perhaps?

ulong a = 1;
byte b;
b = a; // Here a ulong is not implicitly convertible to a byte so we
get a
compile error which is correct

//Tony
 
J

JT

Hello!

Good explained thanks!

//Tony

"Rene" <[email protected]> skrev i meddelandet

For the same reason code below does not generate an error.
ulong a = 1;
byte b;
b = Convert.ToByte(a);
There is nothing wrong with code above, in that snippet, you are stating
that you want to convert a ulong to a byte and not to trhow an error if
the conversion overflows. why would the compiler throw a compile error
here??
Like I said before, internally, the C# compiler is taking your foreach
code and creating code that the CLR can understand, **this icludes**
generating code that is doing the **convertion without trhouwing an
error**, something similar to the example avobe.
Ah, because when you do a foreach loop internally you are calling the
GetEnumerator() function wich in turn return an IEnumerator that in turn
returns objects as it collection member, so there is no way to do a
compile time check because the compiler does not whats inside the object.
You can check the definition of the IEnumerator for more info.
If you want to loop throw an array and have the compile time check then do
a "for" loop.
ulong[] vektor = { 100000, 200000, 300000 };
for (int i = 0; i < vektor.Length; i++)
{
byte b = vektor;
Console.WriteLine("i={0}", b);
}
//Tony
"Rene" <[email protected]> skrev i meddelandet
Your foreach loop instructions are basically translated by the C#
compiler into a bunch of other instructions that are understood by the
CLR.
One of the instructions that is emitted on your behalf is an instruction
to convert ulong to a byte without throwing an overflow error.
If you are not ok with this behavior you can change it in code by adding
the check using word:
checked
{
ulong[] vektor = { 100000, 200000, 300000 };
foreach (byte b in vektor)
{
Console.WriteLine("i={0}", b);
}
}
Hello!
Why does not this cause a compile error because a ulong has never been
implicitly convertible to byte?
ulong[] vektor = {100000,200000,300000};
foreach(byte b in vektor)
{
Console.WriteLine("i={0}", b);
}
If I have these statements below then I get a compile error.
But it's almost the same as above. Is a bug perhaps?
ulong a = 1;
byte b;
b = a; // Here a ulong is not implicitly convertible to a byte so we
get a
compile error which is correct
//Tony- Hide quoted text -


- Show quoted text -


I was looking at the VS options (Tools... Options...). I found a
setting for VB in Projects and Solutions, Option Strict, that when
checked will require explicit conversions, but I didn't see anything
for C#. However, I certainly wouldn't advise anyone to use VB because
of that. :^>

Since I haven't changed project Build settings from the defaults, I
don't know if this would be caught or not, but you could probably go
into the Project Properties, the Build tab, and change settings to
give you more control over your error reporting. You might try
unchecking the Optimize code checkbox. Make sure Warning Level is set
to the highest number. Make sure the Suppress warnings text box is
clear. Under Treat warnings as errors, check the Specific warnings
radio button and specify a warning that you would want elevated to an
error. I don't know what that would be, but I think the Help files
might give you that.

JT
 

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