-
Notifications
You must be signed in to change notification settings - Fork 4.7k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
The new SZGenericArrayEnumerator unexpectedly throws errors for empty collections #94256
Comments
Tagging subscribers to this area: @dotnet/area-system-linq Issue DetailsDescriptionHello! We encountered an issue related to the base Reproduction StepsCreate an empty list like this: List<int> items = new List<int>(); Imagine that you have a more generic method accepting IEnumerable as a parameter and you call that method and pass the empty list. Inside the method you want to move and access the current item: private void EnumerateCollection(IEnumerable<int> items)
{
IEnumerator<int> enumerator = items.GetEnumerator();
enumerator.MoveNext();
int current = enumerator.Current;
} If you check for the Current directly, you will get: System.InvalidOperationException: 'Enumeration has not started. Call MoveNext.' The type of the enumerator is: SZGenericArrayEnumerator. Prior to NET 8 preview 2, in the same setup you would get a System.Collections.Generic.List.Enumerator and you would not get errors, the Current would be 0. It seems that the new and concrete implementation for the enumerator that is returned for the base types is causing the error. This may cause runtime issues with existing application if they are run in .net8.0. Expected behaviorThe Current should not throw. Actual behaviorErrors are thrown. Regression?Yes, the behavior was different in .NET 8 preview 1 and before. Known WorkaroundsUse MoveNext and only access the Current item if the enumerator has successfully moved to the next position. private void EnumerateCollection(IEnumerable<int> items)
{
IEnumerator<int> enumerator = items.GetEnumerator();
if (enumerator.MoveNext())
{
int current = enumerator.Current;
}
} ConfigurationNo response Other informationNo response
|
I says in the documentation for IEnumerable that
I wouldnt expect any particular behaivour where it explicitly says it is undefined? |
Tagging subscribers to this area: @dotnet/area-system-runtime Issue DetailsDescriptionHello! We encountered an issue related to the base Reproduction StepsCreate an empty list like this: List<int> items = new List<int>(); Imagine that you have a more generic method accepting IEnumerable as a parameter and you call that method and pass the empty list. Inside the method you want to move and access the current item: private void GetNext(IEnumerable<int> items)
{
IEnumerator<int> enumerator = items.GetEnumerator();
enumerator.MoveNext();
int current = enumerator.Current;
} If you check for the Current directly, you will get: System.InvalidOperationException: 'Enumeration has not started. Call MoveNext.' The type of the enumerator is: SZGenericArrayEnumerator. Prior to NET 8 preview 2, in the same setup you would get a System.Collections.Generic.List.Enumerator and you would not get errors, the Current would be 0. It seems that the new and concrete implementation for the enumerator that is returned for the base types is causing the error. This may cause runtime issues with existing application if they are run in .net8.0. Expected behaviorThe Current should not throw. Actual behaviorErrors are thrown. Regression?Yes, the behavior was different in .NET 8 preview 1 and before. Known WorkaroundsUse MoveNext and only access the Current item if the enumerator has successfully moved to the next position. private void GetNext(IEnumerable<int> items)
{
IEnumerator<int> enumerator = items.GetEnumerator();
if (enumerator.MoveNext())
{
int current = enumerator.Current;
}
} ConfigurationNo response Other informationNo response
|
This is still within contract for IEnumerator types. You're not supposed to evaluate |
I agree that you should not evaluate |
I wouldn't agree with that. Calling Put differently, what is a valid return value for |
Let's say that the undefined behavior has changed 🙂 I understand that you don't want to consider this an issue because of the incorrect usage. Just have in mind that many existing applications for one reason or another may depend on this undefined behavior and upgrading to .NET8 may cause issues. |
But for real, relying on Undefined Behavior is a programming cardinal sin and you should repent. If this were in C/C++ you could find the compiler rewriting your method eliding any and all evaluation, and even time-travel that result up to all its callers. |
Description
Hello! We encountered an issue related to the base
SZGenericArrayEnumerator
type and its Current position. This seems to be a breaking change as the issue got introduced in .NET 8 preview 2 - https://versionsof.net/core/8.0/8.0.0-preview.2/.Reproduction Steps
Create an empty list like this:
Imagine that you have a more generic method accepting IEnumerable as a parameter and you call that method and pass the empty list. Inside the method you want to move and access the current item:
If you check for the Current directly, you will get: System.InvalidOperationException: 'Enumeration has not started. Call MoveNext.'
If you call MoveNext() and then check the Current, you will get: System.InvalidOperationException: 'Enumeration already finished.'
The type of the enumerator is: SZGenericArrayEnumerator.
Prior to NET 8 preview 2, in the same setup you would get a System.Collections.Generic.List.Enumerator and you would not get errors, the Current would be 0.
It seems that the new and concrete implementation for the enumerator that is returned for the base types is causing the error. This may cause runtime issues with existing application if they are run in .net8.0.
Expected behavior
The Current should not throw.
Actual behavior
Errors are thrown.
Regression?
Yes, the behavior was different in .NET 8 preview 1 and before.
Known Workarounds
Use MoveNext and only access the Current item if the enumerator has successfully moved to the next position.
Configuration
No response
Other information
No response
The text was updated successfully, but these errors were encountered: