为什么集合的评估顺序与使用条件运算符的其他类型的评估顺序不同

 Katycui 发布于 2023-02-08 16:44

尝试实现一个GetHashCode覆盖类似于Jon的Skeet的建议,在什么是覆盖System.Object.GetHashCode的最佳算法?我注意到在评估顺序中有一些奇怪的行为,当使用条件运算符对类中的集合属性进行空检查时,会导致语法错误.

考虑以下:

public class Foo
{

    public String Name { get; private set; }
    public List Bar { get; private set; }

    public override Int32 GetHashCode()
    {
        unchecked
        {
            int hash = 17;
            hash = hash * 23 + this.Name == null ? 0 : this.Name.GetHashCode();
            hash = hash * 23 + this.Bar == null ? 0 : this.Bar.GetHashCode();
            return hash;
        }
    }
}

当您收到语法错误时hash = hash * 23 + this.Bar == null ? 0 : this.Bar.GetHashCode();,此代码将无法编译,特别是指向hash * 23 + this.Bar段.

错误是

运算符'+'不能应用于'int'和'System.Collections.Generic.List'类型的操作数

你没有得到相同的错误,hash = hash * 23 + this.Name == null ? 0 : this.Name.GetHashCode();虽然唯一的区别Name是a stringBar是a List<>.

将整个条件操作包装在一组括号中会删除错误,但这仍然无法解释为什么集合属性的处理方式与字符串属性不同.

是否有一个原因我不知道这导致对不同类型的操作进行不同的评估?

2 个回答
  • 看看这个功能:

    void Crash() {
        int hash = 123;
        int crash = hash * 23 + this.Name == null ? 0 : this.Name.GetHashCode();
    }
    

    它与你的相似 - 我删除了无法编译的部分.

    Name设置为null (演示)时,此功能将以您GetHashCode()想要的方式崩溃.这看起来很奇怪,因为乍一看检查的性能null是存在的.

    但是,检查它是错误的null:C#与null整个表达式进行比较:

    hash * 23 + this.Name
    

    这是一个有效的字符串连接.

    这提供了一个线索,以解决您的"玄机":这是不是说其实Bar是一个集合错误导致编译错误,但事实证明Namestring被错误地避免编译错误.

    2023-02-08 16:46 回答
  • 区别在于它hash * 23 + this.Name == null是一个有效的表达式,而hash * 23 + this.Bar == null不是.+用于算术和字符串连接,但不用于向列表中添加元素.在这两种情况下,整个hash * 23 + this.... == null都被视为?:操作员的条件.

    2023-02-08 16:47 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有