繁体   English   中英

带有未初始化的可为空类型的Enumerable Min和Max扩展方法行为所迷惑

[英]Bewildered by Enumerable Min and Max extension methods behavior with uninitialized nullable types

有人可以阐明(或自由推测)为什么Linq Min和Max扩展方法在处理未初始化的可空类型时会表现出它们的行为吗?

也许最简单的方法是显示我观察到的内容:

int? a = null;
int? b = 1;

Nullable.Compare(a, b);                            // -1, indicating null is smaller then 1
new int?[] { null, 1 }.OrderBy(x => x).First();    // null, null smaller then 1

new[] { 0, 1 }.Min();                              // 0 as expected

new int[] { }.Min();                               // invalidoperator exception as expected

到目前为止一切顺利,但随后...

new int?[] { null, 1 }.Max();                       // 1 as expected
new int?[] { null, 1 }.Min();                       // 1 ?????, why not null ?

new int?[] { null, null }.Min();                    // null, why null now and not above ?

new int?[] { }.Min();                               // null, and no exception ???

我承认,我一开始并不特别在意Nullable类型,但这是另一个故事:-)

我仍然对为什么以这种方式实施感到好奇。

干杯,巴特

您可以反编译Nullable源代码,从而得到以下定义:

    public static int Compare<T>(Nullable<T> n1, Nullable<T> n2) where T : struct
    {
        if (n1.HasValue) {
            if (n2.HasValue) return Comparer<T>.Default.Compare(n1.value, n2.value);
            return 1;
        }
        if (n2.HasValue) return -1;
            return 0;
    }

看起来nullable.compare方法在n1为null和n2具有值的情况下有意返回-1。

同样,您可以反编译linq源代码,从而得到以下定义:

    public static int? Min(this IEnumerable<int?> source) {
        if (source == null) throw Error.ArgumentNull("source");
        int? value = null;
        foreach (int? x in source) {
            if (value == null || x < value)
                value = x;
        }
        return value;
    }

源对象上的迭代检查值是否为null,如果为null,则将x分配给value *。 这只是linq的默认实现,它是在与null进行比较时返回一个数字作为最小值。

关于为什么要这样做的问题,我认为这是因为null表示缺少值而不是整数值,并且他们(编写linq的人)不同意可比方法的最初构建方式。 他们可能发现没有正常执行路径,其中空将被认为是最好的回答“什么是空值和整数的这个列表的最小值 ”。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM