随笔 - 139  文章 - 0  评论 - 421  阅读 - 17万

再谈值类型和null的比较

原来的随笔回复很多,不方便大家讨论这个诡异的问题了,原文章可以参考这里,里面有详细的说明:

 http://www.cnblogs.com/xuefeng1982/archive/2009/11/13/1602358.html

通过几天的研究,问题终于有了结果了,分享给大家!


我也是请教了一个朋友才了解到这些的,十分感谢懿民帮助 !

通过查看C#编译器的源代码,我们会发现他在编译以下代码的时候:

            public static bool operator ==(MyStruct2 s1, MyStruct2 s2)
            {
                return s1.Value == s2.Value;
            }

需要执行如下代码:

        // Equality operators are special. If the return type is bool and the parameter types
        // are the same then they treat null as a value and return bool.
        if (fEqOp && nin.FAlwaysNull()) {
            ASSERT((ek == EK_EQ || ek == EK_NE) && typeRetRaw->isPredefType(PT_BOOL) && paramsRaw->Item(0) == paramsRaw->Item(1));
            // At least one of them is a constant null.
            EXPR * exprRes;
 
            if (nin.rgfNull[0] && nin.rgfNull[1]) {
                // Both are constant nulls.
                exprRes = newExprConstant(tree, typeRetRaw, ConstValInit(ek == EK_EQ));
                exprRes = AddSideEffects(tree, exprRes, exprVal2, true, true);
                return AddSideEffects(tree, exprRes, exprVal1, true, true);
            }
 
            if (nin.rgfNull[0] ? !exprVal2->type->isNUBSYM() : !exprVal1->type->isNUBSYM()) {
                // One is null and the other is not nullable.
                exprRes = newExprConstant(tree, typeRetRaw, ConstValInit(ek == EK_NE));
                exprRes = AddSideEffects(tree, exprRes, exprVal2, true, true);
                return AddSideEffects(tree, exprRes, exprVal1, true, true);
            }
 
            // Generate seq(a, !b.HasValue) or rev(!a.HasValue, b).
            exprRes = BindNubHasValue(tree, nin.rgfNull[0] ? exprVal2 : exprVal1, ek == EK_NE);
            return AddSideEffects(tree, exprRes, nin.rgfNull[0] ? exprVal1 : exprVal2, nin.rgfNull[0], true);
        }

大家注意最上面那行注释:那么判等操作符是特殊的,如果返回值是bool并且参数类型是一样的,那么就把null作为值类型来看待,返回一个bool.

可见,C#编译器是有意这样来设计的,这不是一个bug,值类型只要提供了==运算符重载,并且参数类型是一样的,值类型就可以和null 比较(==,!=,<,>,<=,>=都有类似的特殊性),但是结果始终是确定的,所以这个比较意义不是很大,但是C#编译器的确是允许类似的比较的,他认为这个行为是合法的!这样设计的原因很可能是为了和可空类型在语义上保持一致!

请大家多多指教啊!
posted on   周雪峰  阅读(2007)  评论(9编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 分享 3 个 .NET 开源的文件压缩处理库,助力快速实现文件压缩解压功能!
· Ollama——大语言模型本地部署的极速利器
· [AI/GPT/综述] AI Agent的设计模式综述
< 2009年11月 >
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30 1 2 3 4 5
6 7 8 9 10 11 12

点击右上角即可分享
微信分享提示