Skip to content
Closed
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -116,7 +116,7 @@ private void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> enumerable)
// back-compat with subclasses that may have overridden the enumerator behavior.
if (enumerable.GetType() == typeof(Dictionary<TKey, TValue>))
{
Dictionary<TKey, TValue> source = (Dictionary<TKey, TValue>)enumerable;
Dictionary<TKey, TValue> source = Unsafe.As<Dictionary<TKey, TValue>>(enumerable);

if (source.Count == 0)
{
Expand Down Expand Up @@ -161,7 +161,7 @@ private void AddRange(IEnumerable<KeyValuePair<TKey, TValue>> enumerable)
}
else if (enumerable.GetType() == typeof(List<KeyValuePair<TKey, TValue>>))
{
span = CollectionsMarshal.AsSpan((List<KeyValuePair<TKey, TValue>>)enumerable);
span = CollectionsMarshal.AsSpan(Unsafe.As<List<KeyValuePair<TKey, TValue>>>(enumerable));
Copy link
Member

@stephentoub stephentoub Aug 13, 2025

Choose a reason for hiding this comment

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

Thanks, but I do not want to introduce unsafe code for things like this. If it's material, the cast should be elided by the JIT, if it's not already.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@EgorBo The diffs show the cast is not elided.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Thanks, but I do not want to introduce unsafe code for things like this.

We already use the unsafe method CollectionsMarshal.AsSpan here.

Copy link
Member

Choose a reason for hiding this comment

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

Thanks, but I do not want to introduce unsafe code for things like this.

We already use the unsafe method CollectionsMarshal.AsSpan here.

That doesn't mean we need to add more. They're also "unsafe" in very different ways. Unsafe.As lets you completely break type safety. AsSpan is on the marshal class only because there's a potential for someone to make changes that get lost if they get the span, then edit the list in a way that causes it to grow, and then edit the span; it's not a memory safety issue.

Copy link
Member

Choose a reason for hiding this comment

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

@EgorBo The diffs show the cast is not elided.

Yes, this is a known issue, I can't find the exact github issue, but I do remember it exists. Basically, the same repro I mentioned here: #118655 (comment)
I'll try to fix it in .NET 11.0. In case if you're looking for an inspiration on what to contribute to dotnet/runtime repo, anything that replaces unsafe code with safe (ideally, with zero overhead) would be more than appreciated 🙂

Copy link
Contributor Author

Choose a reason for hiding this comment

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

}
else
{
Expand Down
Loading