为什么C#编译器不会抛出null的逻辑比较?

Poo*_*hop 15 c# logic

我昨天和朋友一起吃午饭,他们null在C#中抱怨.他说那null是不合逻辑的.我决定测试他的说法,所以我测试了一些简单的逻辑命题:

Console.WriteLine(null == null); //True
//Console.WriteLine(null == !!null); //BOOM

Console.WriteLine(10 >= null); //False
Console.WriteLine(10 <= null); //False

Console.WriteLine(!(10 >= null)); //True
Console.WriteLine(!(10 <= null)); //True
Run Code Online (Sandbox Code Playgroud)

检查平等似乎很简单,这就是我所期望的.然而,更多/更少的陈述是逻辑矛盾,我觉得这真的很混乱!这些不应该抛出?否定操作会像您期望的那样抛出.

如果我尝试null在Ruby或Python中运行比较(除了相等),我会得到一个类型错误:"无法将数字与nil进行比较".为什么C#不这样做?

EJo*_*ica 13

好问题.

尽量不要将其null视为具体的价值,而是"在这里看不到任何东西".该文档定义null

null关键字是表示一个空引用,一个不指向任何对象文字.

考虑到这一点,null不是一个对象的事实意味着经典的思想规律并不完全适用于它(或者,至少,它不适用于它应用于实际对象的方式).

话虽这么说,事实上,10 >= null并且10 <= null两者都false严格来说并不是矛盾 - 毕竟,null实际上并非一无所获.如果你说10 >= (some actual thing)并且10 <= (some actual thing)都是假的,那么显然这是矛盾的,但如果没有一些实际的对象,你就不能在经典意义上产生矛盾.亚里士多德从形而上学中对法律的定义如下:

同一个东西既不属于同一个对象又不属于同一个对象,也可能属于所有其他可能的规范,这些都是不可能的,让它们被添加以满足当地的反对意见......

所以,从某种意义上说,我们在这里有一点"漏洞".至少亚里士多德制定了"不矛盾法",它特指的是对象.当然,在这一点上,对"非矛盾法"有多种解释.

现在,转向的情况10 + null.我们可以说这就像null + 10它更容易一样.从某种意义上说,在这一点上应该发生什么 - 应该null"吞噬"10,或者我们应该只说"10 +(什么都没有)真的应该等于10"?说实话,从逻辑的角度来看,我没有一个非常有说服力的答案,而是说"嗯,这是一种设计选择".我怀疑语言设计者要区分10 + null10 + 0,但我没有文件证明.(实际上,如果它们是相同的话会有点奇怪;毕竟,0是一个可以从自然数构造的实际值,但是null"无论什么价值都没有").


Tig*_*ran 10

我知道它在语言规范的某个地方,这不是我有兴趣知道的.我有兴趣理解为什么这些逻辑违规似乎存在,或者我对逻辑规律的理解是不正确的.

编程语言不应该遵循哲学隐含的逻辑规则,无论如何,编程语言意味着解决具体的行业/业务相关问题.许多语言甚至不遵守数学思维规则,如代数表达式,范畴理论等等,所以......

10必须大于或小于null ...不应该吗?

不,"null关键字是表示空引用的文字,不引用任何对象的文字",并且根据C#规则,编译器扫描所提供类型的可用运算符,如果其中一个参与者是null,则表达式的结果将是null.

寻找提升的运营商

10 + null如何才能为null?

往上看.

  • @Tigran Logic和哲学不一样,我不是在讨论哲学 - 我相信你提到了这一点.逻辑是科学和编程的基础,非常重要. (2认同)

Kev*_*vin 4

如果您不认为“空”是一个值,它会有所帮助 - 它是一个虚无或缺乏值的概念。不仅仅是 C# - 您还会在 SQL 中遇到同样的情况(NULL + 'asdf' 将导致 NULL。)

所以像 (NULL < 10) 这样的东西本身并没有什么逻辑意义——你正在将虚无的概念与实际数字进行比较。从技术上讲,不,虚无不小于 10。它也不大于 10。这就是为什么它在这两种情况下都会返回 false。

警告您远离 NULL 的原因与逻辑无关。下面是一个很好的例子,说明了为什么 C# 中的 NULL 通常会导致 bug/错误:

private NumericalAnalysis AnalyzeNumber(int someValue)
{
    if (someCondition)
        return null;
    return new NumericalAnalysis(someValue);
}
Run Code Online (Sandbox Code Playgroud)

...好吧,现在我们可以调用AnalyzeNumber() 并开始使用NumericalAnalysis:

NumericalAnalysis instance = AnalyzeNumber(3);
if (instance.IsPrime)
    DoSomething();
Run Code Online (Sandbox Code Playgroud)

... 哎呀!你刚刚遇到了一个错误。您调用了AnalyzeNumber(),但在使用它之前没有检查返回值是否为null。毕竟,AnalyzeNumber() 有时会返回空值 - 因此当调用 instance.IsPrime 时,它​​会崩溃。实际上,每次调用该函数时,您都必须执行“if (myVar == null)”检查- 如果您忘记了,您只是引入了一个错误。