空数组“等于”的定义以及 .NET 和 .NET 核心之间的区别

Đøh*_*rck 6 c# arrays .net-core

我昨天编写了一些单元测试,它们在 .NET 4.6.1 中通过但在 .NET core 3.0 中失败,因为在该测试期间生成的数组实例的数量在两种环境中是不同的。经过一番调查,结果发现用 LINQ 创建的空数组的数量是不同的。我终于能够将它转储到这个测试中:

    [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
    }
Run Code Online (Sandbox Code Playgroud)

我的问题是:有谁知道实现的不同之处?如果集合没有元素,ToArray() 是否可能在 .NET 核心中返回一个 Array.Empty<> 单例实例,但在 .NET 中不返回?

can*_*on7 5

如果集合没有元素,ToArray() 是否可能在 .NET 核心中返回一个 Array.Empty<> 单例实例,但在 .NET 中不返回?

是的。Linq 在 .NET Core 中得到了很多速度优化。

在 .NET Framework 中,Enumerable.ToArray()调用Buffer<TElement>.ToArray()new TElement[0]如果缓冲区为空,则返回。

在 .NET Core 中,对于您的特定情况<array>.Where(...).ToArray()Enumerable.ToArray()调用IIListProvider<TSource>.ToArray(),它由 实现WhereArrayIterator<TSource>.ToArray(),调用new LargeArrayBuilder<TSource>(_source.Length)使用Array.Empty<T>.