I have written some unit tests yesterday that pass in .NET 4.6.1 but fail in .NET core 3.0 because the number of array instances that is generated during that test is different in both environments. After some investigation it turned out that the count of empty arrays created with LINQ is different. I was finally able to dump it down to this test:
[Test]
public void ArrayTest()
{
var numbers = Enumerable.Range(1, 5);
int[] items1 = numbers.Where(i => i > 5).ToArray();
int[] items2 = numbers.Where(i => i > 5).ToArray();
Assert.IsFalse(items1 == items2); // fails in .NET core 3 but passes in .NET 461
Assert.IsFalse(items1.Equals(items2)); // fails in .NET core 3 but passes in .NET 461
}
My question is: does anyone know where the implementation is different? Does ToArray() maybe return an Array.Empty<> singleton instance in .NET core but not in .NET if the collection has no elements?
Does ToArray() maybe return an Array.Empty<> singleton instance in .NET core but not in .NET if the collection has no elements?
Yes. Linq was given a lot of speed optimizations in .NET Core.
In .NET Framework, Enumerable.ToArray()
calls Buffer<TElement>.ToArray()
, which returns a new TElement[0]
if the buffer is empty.
In .NET Core, for your specific case of <array>.Where(...).ToArray()
, Enumerable.ToArray()
calls IIListProvider<TSource>.ToArray()
, which is implemented by WhereArrayIterator<TSource>.ToArray()
, which calls new LargeArrayBuilder<TSource>(_source.Length)
, which uses Array.Empty<T>
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With