线上报来一个问题,说用户的数据丢失了。开发经过紧张的调查。终于找到了原因。

if (newData.GetValue(rowIndex) == oldData.GetValue(rowIndex))
{ .................. } public object GetValue(string fieldName))
{
...............
return values[filedName]; //这是一个简单类型: int,string
}

问题出在了 if 中的比较上。  values[rowIndex] 中保存的是一个整数,开发认为两个整数比较实用 ==  就可以了。

但是 values[rowIndex] 中的整数经过 GetValue返回后被作为 object 对象返回了,这时如果还使用 == 进行比较就会出现不等的情况。

我们来看一个更全面的例子:

static void Main(string[] args)
{
object value1 = new object();
object value2 = new object(); value1 = ;
value2 = ; Console.WriteLine("value1 == value2 {0}", (value1 == value2).ToString());
Console.WriteLine("vvalue1.Equals(value2) {0}", value1.Equals(value2).ToString());
Console.WriteLine("Equals(value1, value2) {0}", Equals(value1, value2).ToString());
Console.WriteLine("ReferenceEquals(value1,value2) {0}", ReferenceEquals(value1,value2).ToString());
}

运行结果

value1  == value2 False
value1.Equals(value2) True
Equals(value1, value2) True
ReferenceEquals(value1,value2) False

如果我们将value1, value2 都定义为数字,但是一个是long,一个是uint.

static void Main(string[] args)
{
   long value1 = ;
int value2 = ; Console.WriteLine("value1 == value2 {0}", (value1 == value2).ToString());
Console.WriteLine("value1.Equals(value2) {0}", value1.Equals(value2).ToString());
Console.WriteLine("Equals(value1, value2) {0}", Equals(value1, value2).ToString());
Console.WriteLine("ReferenceEquals(value1,value2) {0}", ReferenceEquals(value1,value2).ToString()); }

看一下运行结果 ,使用  ==  ,和 value1.Equals  方法比较是相等的。

value1  == value2 True
value1.Equals(value2) True
Equals(value1, value2) False
ReferenceEquals(value1,value2) False

结合上面两个例子,我们定义一个long 变量, 一个unit 变量, 给它们赋值之后,再将这两个变量赋值给两个object 对象。

 static void Main(string[] args)
{
object value1 = new object();
object value2 = new object(); long lgval = ;
int ival = ; value1 = lgval;
value2 = ival; Console.WriteLine("lgval == ival {0}", (lgval == ival).ToString());
Console.WriteLine("value1 == value2 {0}", (value1 == value2).ToString());
Console.WriteLine("value1.Equals(value2) {0}", value1.Equals(value2).ToString());
Console.WriteLine("Equals(value1, value2) {0}", Equals(value1, value2).ToString());
Console.WriteLine("ReferenceEquals(value1,value2) {0}", ReferenceEquals(value1,value2).ToString()); }

可以看到,除去值类型 lgval 和 uval 相等外,其它都是不相等的。

lgval  == uval True
value1 == value2 False
value1.Equals(value2) False
Equals(value1, value2) False
ReferenceEquals(value1,value2) False

是不是很抓狂? 到底什么情况下相等?什么情况下不等?我们先将上面的结果总结一下。

 
 

value1 和value2都是Object 对象

含有相同类型的值对象(int)

含有相同的值

value1 是long,value2 是 int

含有相同的值

value1 和value2都是Object 对象

含有不同类型的值对象(long,int)

含有相同的值

value1  == value2
false  true   false
value1.Equals(value2)
true  true   false
Equals(value1, value2)
 true false   false
ReferenceEquals(value1,value2)
 false false   false

如果将一个值类型赋值给一个object 对象后,如何判断相等? 微软官方也没有给出一个标准的说法。从测试的角度来看。

两个比较的 object 中的内容如果类型相同,可以使用Equals 来进行比较。

不过我个人还是建议如果是比较值,还是转换为对应的值类型进行比较,这样比较清晰,不容易犯错,大家也不用搞清楚 == 和 Equals 之前的细微差别。

ps: 如果object 的类型是 string , 上面的结果又会有所不同,有兴趣的同学可以自己尝试一下。

一次线上问题引发的对于C#中相等判断的思考的更多相关文章

  1. 简述C#中IO的应用 RabbitMQ安装笔记 一次线上问题引发的对于C#中相等判断的思考 ef和mysql使用(一) ASP.NET/MVC/Core的HTTP请求流程

    简述C#中IO的应用   在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.I ...

  2. 对“线上问题 不能gdb调试怎么处理??“”的思考

    Q1:线上问题的process 都为release版本!不带调试信息怎么查?(目前有时需要查线上问题, 不得不解决这个问题) 之前查问题都是编译环境编译一个带有debug信息的版本进行替换来调试,但是 ...

  3. 测试通过!为何线上还有很多BUG?实践中的质量控制

    质量控制 大多数测试人员认为测试工作是发现bug,虽然这是测试的主要任务,但其实测试最重要的任务是质量控制,而发现bug和验证bug只是质量控制的一个重要环节而已. 我想很多测试人员都经历过这样的场景 ...

  4. CDOJ1339 郭大侠与线上游戏(维护一个set中的中位数——平衡树/双set)

    http://acm.uestc.edu.cn/#/problem/show/1339 题意:有三种操作,分别是. 1.向队列推入一个数x. 2.弹出这个队列的第一个数字 3.查询这个队列的中位数是多 ...

  5. 线上bug分析

    昨天下午大神把组内几十号人召集在一起开Online bug分析大会,主要是针对近期线上事故从事故原因和解决方案两个维度来分析. 对金融软件来说,每一次的线上事故都有可能给公司带来重大的损失,少扣了用户 ...

  6. CAS (15) — CAS 线上环境 Ehcache Replication 的非稳定重现错误 java.util.ConcurrentModificationException

    CAS (15) - CAS 线上环境 Ehcache Replication 的非稳定重现错误 摘要 线上环境在 EhCache Replication 过程中出现 java.util.Concur ...

  7. gor实现线上HTTP流量复制压测引流

    一.使用背景 gor 是一款go语言实现的简单的http流量复制工具,它的主要目的是使你的生产环境HTTP真实流量在测试环境和预发布环境重现.只需要在 代理例如nginx入口服务器上执行一个进程,就可 ...

  8. redis扫描特定keys脚本,可避免阻塞,不影响线上业务

    #!/bin/sh ## 该脚本用来查询redis集群中,各个实例当中特定前缀的key,对应只需要修改redis的其中一个实例的 host和port## 脚本会自动识别出该集群的所有实例,并查出对应实 ...

  9. 线上服务宕机,码农试用期被毕业,原因竟是给MySQL加个字段

    1. 问题:怎么给线上表加字段? 工作中最常遇到的问题,怎么给线上频繁使用的大表添加字段? 比如:给下面的用户表(user)添加年龄(age)字段. CREATE TABLE `user` ( `id ...

随机推荐

  1. springboot情操陶冶-@Conditional和@AutoConfigureAfter注解解析

    承接前文springboot情操陶冶-@Configuration注解解析,本文将在前文的基础上阐述@AutoConfigureAfter和@Conditional注解的作用与解析 1.@Condit ...

  2. 使用vue之directive设计列表加载更多

    背景 之前写过一篇<纯JS实现加载更多(VUE框架)>,它的逻辑思路比较清晰易懂,而今天看了一天公司项目的部分功能代码,发现同事们写的加载更多的功能更加的有趣,而且易于封装到一个组件当中, ...

  3. C#字符串。

    string类型不能被继承,它是密封类,sealed. 一.字符串的特性. 1.不可变性. class Program { static void Main(string[] args) { stri ...

  4. IIS发布网站 报错500.19 错误解决过程记录

    首先先报上我的环境 WindowsServer 2012 IIS 8.5 网站是FrameWork 4.0 发布网站后浏览,报错信息如下: 解决过程记录如下: 1.看到这个问题首先想到的是权限问题,设 ...

  5. ASP.NET Core入门

    一.搭建开发环境 在Windows平台下,开发.NET Core 程序需要安装如下内容: 1. .NET Core runtime 2. Visual Studio 2015 with Update ...

  6. JQuery官方学习资料(译):操作元素

      获取和设置元素的信息     有很多种方式可以改变现有的元素,最常见的是改变HTML内容或者元素的属性.JQuery提供了简单的夸浏览器的方法来帮助你实现元素信息的获取和设置. .html():获 ...

  7. Core知识整理

    概述 Commond-Line ASP.NET结构文件 Startup 配置文件 中间件和依赖注入 依赖注入原理 框架自带的依赖注入(IServiceCollection) 依赖注入生命周期 依赖注入 ...

  8. .NET 中的序列化 & 反序列化

    序列化:将对象的状态信息及类型信息,转换为一种易于传输或存储形式(流,即字节序列)的过程. 下图为序列化过程图示,图片来自微软官方文档: 反序列化:与序列化相反,将流转换为对象的过程. 常用的有二进制 ...

  9. 【Java每日一题】20170207

    20170206问题解析请点击今日问题下方的“[Java每日一题]20170207”查看(问题解析在公众号首发,公众号ID:weknow619) package Feb2017; public cla ...

  10. VM扩展磁盘大小

    1.通过扩展磁盘的方法增大磁盘大小 2.然后开启Linux 此时查看磁盘  df -h 并没有增加,使用 fdisk -l 查看发现已经扩展 使用 root 用户,进入到 ~ 家目录下面. 3.使用 ...