Skip to content

Conversation

Copy link
Contributor

Copilot AI commented Sep 18, 2025

Fixes a regression introduced in .NET 9 where ElementAtOrDefault on DefaultIfEmpty iterators was incorrectly returning the custom default value instead of default(TSource) for out-of-bounds indices.

Problem:

int result = Array.Empty<int>().DefaultIfEmpty(1).ElementAtOrDefault(1);
Console.WriteLine(result); // Prints 1, should print 0

The issue was in DefaultIfEmptyIterator<TSource>.TryGetElementAt which always returned _default (the custom default value) regardless of whether the element was found, instead of returning default(TSource) when found is false.

Root Cause:
The method was setting found = true only for index 0 but always returning _default, even for out-of-bounds indices where it should return default(TSource).

Fix:

  • Modified TryGetElementAt to return _default only when index == 0 and found = true
  • Return default(TSource) for all other out-of-bounds indices where found remains false
  • Added comprehensive regression test covering both value and reference types

Behavior After Fix:

  • Array.Empty<int>().DefaultIfEmpty(999).ElementAtOrDefault(0) → Returns 999 (unchanged)
  • Array.Empty<int>().DefaultIfEmpty(999).ElementAtOrDefault(1) → Returns 0 (was 999)
  • Array.Empty<string>().DefaultIfEmpty("default").ElementAtOrDefault(1) → Returns null (was "default")

The fix ensures ElementAtOrDefault behaves consistently with the documented contract of returning default(TSource) for out-of-bounds access.

Fixes #119834.


✨ Let Copilot coding agent set things up for you — coding agent works faster and does higher quality work when set up for your repo.

Copilot AI changed the title [WIP] DefaultIfEmptyIterator<TSource>.TryGetElementAt returns _default when not found Fix DefaultIfEmptyIterator.TryGetElementAt returning default value for out-of-bounds indices Sep 18, 2025
Copilot finished work on behalf of eiriktsarpalis September 18, 2025 10:01
@eiriktsarpalis eiriktsarpalis marked this pull request as ready for review September 18, 2025 10:36
Copilot AI review requested due to automatic review settings September 18, 2025 10:36
Copy link
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull Request Overview

Fixes a regression in .NET 9 where ElementAtOrDefault on DefaultIfEmpty iterators incorrectly returned the custom default value instead of default(TSource) for out-of-bounds indices.

  • Modified TryGetElementAt to return the custom default only for index 0, and default(TSource) for out-of-bounds indices
  • Added comprehensive regression tests covering both value and reference types with various out-of-bounds scenarios

Reviewed Changes

Copilot reviewed 2 out of 2 changed files in this pull request and generated no comments.

File Description
src/libraries/System.Linq/src/System/Linq/DefaultIfEmpty.SpeedOpt.cs Fixed TryGetElementAt logic to return correct defaults for out-of-bounds access
src/libraries/System.Linq/tests/DefaultIfEmptyTests.cs Added regression test verifying ElementAtOrDefault behavior for out-of-bounds indices

@stephentoub stephentoub merged commit 7551cea into main Sep 18, 2025
91 checks passed
@stephentoub stephentoub deleted the copilot/fix-119834 branch September 18, 2025 12:53
@eiriktsarpalis
Copy link
Member

/backport to release/10.0-staging

@github-actions
Copy link
Contributor

Started backporting to release/10.0-staging: https://github.com/dotnet/runtime/actions/runs/17829880616

@eiriktsarpalis
Copy link
Member

/backport to release/9.0-staging

@github-actions
Copy link
Contributor

Started backporting to release/9.0-staging: https://github.com/dotnet/runtime/actions/runs/17829888883

@github-actions
Copy link
Contributor

@eiriktsarpalis an error occurred while backporting to "release/10.0-staging", please check the run log for details!

Error: The specified backport target branch "release/10.0-staging" wasn't found in the repo.

@eiriktsarpalis
Copy link
Member

/backport to release/10.0

@github-actions
Copy link
Contributor

xtqqczze pushed a commit to xtqqczze/dotnet-runtime that referenced this pull request Sep 20, 2025
…r out-of-bounds indices (dotnet#119838)

* Initial plan

* Fix DefaultIfEmptyIterator.TryGetElementAt to return default when element not found

Co-authored-by: eiriktsarpalis <[email protected]>

* Add regression test and finalize fix for DefaultIfEmptyIterator.TryGetElementAt

Co-authored-by: eiriktsarpalis <[email protected]>

---------

Co-authored-by: copilot-swe-agent[bot] <[email protected]>
Co-authored-by: eiriktsarpalis <[email protected]>
@jeffhandley
Copy link
Member

/backport to release/10.0-rc2

@github-actions
Copy link
Contributor

Started backporting to release/10.0-rc2: https://github.com/dotnet/runtime/actions/runs/17952465675

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

DefaultIfEmptyIterator<TSource>.TryGetElementAt returns _default when not found

4 participants