Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Merged
10 changes: 7 additions & 3 deletions src/libraries/System.Linq/src/System/Linq/OfType.SpeedOpt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -52,17 +52,21 @@ public override TResult[] ToArray()

public override List<TResult> ToList()
{
var list = new List<TResult>();
SegmentedArrayBuilder<TResult>.ScratchBuffer scratch = default;
SegmentedArrayBuilder<TResult> builder = new(scratch);

foreach (object? item in _source)
{
if (item is TResult castItem)
{
list.Add(castItem);
builder.Add(castItem);
}
}

return list;
List<TResult> result = builder.ToList();
builder.Dispose();

return result;
}

public override TResult? TryGetFirst(out bool found)
Expand Down
22 changes: 22 additions & 0 deletions src/libraries/System.Linq/src/System/Linq/SegmentedArrayBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
using System.Diagnostics;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;

namespace System.Collections.Generic
{
Expand Down Expand Up @@ -251,6 +252,27 @@ public readonly T[] ToArray()
return result;
}

/// <summary>Creates a list containing all of the elements in the builder.</summary>
public readonly List<T> ToList()
{
List<T> result;
int count = Count;

if (count != 0)
{
result = new List<T>(count);

CollectionsMarshal.SetCount(result, count);
ToSpanInlined(CollectionsMarshal.AsSpan(result));
}
else
{
result = [];
}

return result;
}

/// <summary>Creates an array containing all of the elements in the builder.</summary>
/// <param name="additionalLength">The number of extra elements of room to allocate in the resulting array.</param>
public readonly T[] ToArray(int additionalLength)
Expand Down
40 changes: 30 additions & 10 deletions src/libraries/System.Linq/src/System/Linq/Select.SpeedOpt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Collections.Generic;
using System.Diagnostics;
using System.Runtime.CompilerServices;
using System.Runtime.InteropServices;
using static System.Linq.Utilities;

Expand Down Expand Up @@ -31,15 +32,19 @@ public override TResult[] ToArray()

public override List<TResult> ToList()
{
var list = new List<TResult>();
SegmentedArrayBuilder<TResult>.ScratchBuffer scratch = default;
SegmentedArrayBuilder<TResult> builder = new(scratch);

Func<TSource, TResult> selector = _selector;
foreach (TSource item in _source)
{
list.Add(selector(item));
builder.Add(selector(item));
}

return list;
List<TResult> result = builder.ToList();
builder.Dispose();

return result;
}

public override int GetCount(bool onlyIfCheap)
Expand Down Expand Up @@ -657,7 +662,7 @@ public override IEnumerable<TResult2> Select<TResult2>(Func<TResult, TResult2> s
return sourceFound ? _selector(input!) : default!;
}

private TResult[] LazyToArray()
private TResult[] ToArrayNoPresizing()
{
Debug.Assert(_source.GetCount(onlyIfCheap: true) == -1);

Expand Down Expand Up @@ -691,24 +696,39 @@ public override TResult[] ToArray()
int count = _source.GetCount(onlyIfCheap: true);
return count switch
{
-1 => LazyToArray(),
-1 => ToArrayNoPresizing(),
0 => [],
_ => PreallocatingToArray(count),
};
}

private List<TResult> ToListNoPresizing()
{
Debug.Assert(_source.GetCount(onlyIfCheap: true) == -1);

SegmentedArrayBuilder<TResult>.ScratchBuffer scratch = default;
SegmentedArrayBuilder<TResult> builder = new(scratch);

Func<TSource, TResult> selector = _selector;
foreach (TSource input in _source)
{
builder.Add(selector(input));
}

List<TResult> result = builder.ToList();
builder.Dispose();

return result;
}

public override List<TResult> ToList()
{
int count = _source.GetCount(onlyIfCheap: true);
List<TResult> list;
switch (count)
{
case -1:
list = new List<TResult>();
foreach (TSource input in _source)
{
list.Add(_selector(input));
}
list = ToListNoPresizing();
break;
case 0:
list = new List<TResult>();
Expand Down
12 changes: 8 additions & 4 deletions src/libraries/System.Linq/src/System/Linq/SelectMany.SpeedOpt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -48,15 +48,19 @@ public override TResult[] ToArray()

public override List<TResult> ToList()
{
var list = new List<TResult>();
SegmentedArrayBuilder<TResult>.ScratchBuffer scratch = default;
SegmentedArrayBuilder<TResult> builder = new(scratch);

Func<TSource, IEnumerable<TResult>> selector = _selector;
foreach (TSource element in _source)
foreach (TSource item in _source)
{
list.AddRange(selector(element));
builder.AddRange(selector(item));
}

return list;
List<TResult> result = builder.ToList();
builder.Dispose();

return result;
}
}
}
Expand Down
13 changes: 9 additions & 4 deletions src/libraries/System.Linq/src/System/Linq/SkipTake.SpeedOpt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -491,25 +491,30 @@ public override TSource[] ToArray()

public override List<TSource> ToList()
{
var list = new List<TSource>();

using (IEnumerator<TSource> en = _source.GetEnumerator())
{
if (SkipBeforeFirst(en) && en.MoveNext())
{
int remaining = Limit - 1; // Max number of items left, not counting the current element.
int comparand = HasLimit ? 0 : int.MinValue; // If we don't have an upper bound, have the comparison always return true.

SegmentedArrayBuilder<TSource>.ScratchBuffer scratch = default;
SegmentedArrayBuilder<TSource> builder = new(scratch);
do
{
remaining--;
list.Add(en.Current);
builder.Add(en.Current);
}
while (remaining >= comparand && en.MoveNext());

List<TSource> result = builder.ToList();
builder.Dispose();

return result;
}
}

return list;
return [];
}

private bool SkipBeforeFirst(IEnumerator<TSource> en) => SkipBefore(_minIndexInclusive, en);
Expand Down
40 changes: 28 additions & 12 deletions src/libraries/System.Linq/src/System/Linq/Where.SpeedOpt.cs
Original file line number Diff line number Diff line change
Expand Up @@ -55,18 +55,22 @@ public override TSource[] ToArray()

public override List<TSource> ToList()
{
var list = new List<TSource>();
SegmentedArrayBuilder<TSource>.ScratchBuffer scratch = default;
SegmentedArrayBuilder<TSource> builder = new(scratch);

Func<TSource, bool> predicate = _predicate;
foreach (TSource item in _source)
{
if (predicate(item))
{
list.Add(item);
builder.Add(item);
}
}

return list;
List<TSource> result = builder.ToList();
builder.Dispose();

return result;
}

public override TSource? TryGetFirst(out bool found)
Expand Down Expand Up @@ -199,17 +203,21 @@ public static TSource[] ToArray(ReadOnlySpan<TSource> source, Func<TSource, bool

public static List<TSource> ToList(ReadOnlySpan<TSource> source, Func<TSource, bool> predicate)
{
var list = new List<TSource>();
SegmentedArrayBuilder<TSource>.ScratchBuffer scratch = default;
SegmentedArrayBuilder<TSource> builder = new(scratch);

foreach (TSource item in source)
{
if (predicate(item))
{
list.Add(item);
builder.Add(item);
}
}

return list;
List<TSource> result = builder.ToList();
builder.Dispose();

return result;
}

public override TSource? TryGetFirst(out bool found)
Expand Down Expand Up @@ -398,17 +406,21 @@ public static TResult[] ToArray(ReadOnlySpan<TSource> source, Func<TSource, bool

public static List<TResult> ToList(ReadOnlySpan<TSource> source, Func<TSource, bool> predicate, Func<TSource, TResult> selector)
{
var list = new List<TResult>();
SegmentedArrayBuilder<TResult>.ScratchBuffer scratch = default;
SegmentedArrayBuilder<TResult> builder = new(scratch);

foreach (TSource item in source)
{
if (predicate(item))
{
list.Add(selector(item));
builder.Add(selector(item));
}
}

return list;
List<TResult> result = builder.ToList();
builder.Dispose();

return result;
}

public override TResult? TryGetFirst(out bool found) => TryGetFirst(_source, _predicate, _selector, out found);
Expand Down Expand Up @@ -538,19 +550,23 @@ public override TResult[] ToArray()

public override List<TResult> ToList()
{
var list = new List<TResult>();
SegmentedArrayBuilder<TResult>.ScratchBuffer scratch = default;
SegmentedArrayBuilder<TResult> builder = new(scratch);

Func<TSource, bool> predicate = _predicate;
Func<TSource, TResult> selector = _selector;
foreach (TSource item in _source)
{
if (predicate(item))
{
list.Add(selector(item));
builder.Add(selector(item));
}
}

return list;
List<TResult> result = builder.ToList();
builder.Dispose();

return result;
}

public override TResult? TryGetFirst(out bool found)
Expand Down