一次线上问题引发的对于C#中相等判断的思考
线上报来一个问题,说用户的数据丢失了。开发经过紧张的调查。终于找到了原因。
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#中相等判断的思考的更多相关文章
- 简述C#中IO的应用 RabbitMQ安装笔记 一次线上问题引发的对于C#中相等判断的思考 ef和mysql使用(一) ASP.NET/MVC/Core的HTTP请求流程
简述C#中IO的应用 在.NET Framework 中. System.IO 命名空间主要包含基于文件(和基于内存)的输入输出(I/O)服务的相关基础类库.和其他命名空间一样. System.I ...
- 对“线上问题 不能gdb调试怎么处理??“”的思考
Q1:线上问题的process 都为release版本!不带调试信息怎么查?(目前有时需要查线上问题, 不得不解决这个问题) 之前查问题都是编译环境编译一个带有debug信息的版本进行替换来调试,但是 ...
- 测试通过!为何线上还有很多BUG?实践中的质量控制
质量控制 大多数测试人员认为测试工作是发现bug,虽然这是测试的主要任务,但其实测试最重要的任务是质量控制,而发现bug和验证bug只是质量控制的一个重要环节而已. 我想很多测试人员都经历过这样的场景 ...
- CDOJ1339 郭大侠与线上游戏(维护一个set中的中位数——平衡树/双set)
http://acm.uestc.edu.cn/#/problem/show/1339 题意:有三种操作,分别是. 1.向队列推入一个数x. 2.弹出这个队列的第一个数字 3.查询这个队列的中位数是多 ...
- 线上bug分析
昨天下午大神把组内几十号人召集在一起开Online bug分析大会,主要是针对近期线上事故从事故原因和解决方案两个维度来分析. 对金融软件来说,每一次的线上事故都有可能给公司带来重大的损失,少扣了用户 ...
- CAS (15) — CAS 线上环境 Ehcache Replication 的非稳定重现错误 java.util.ConcurrentModificationException
CAS (15) - CAS 线上环境 Ehcache Replication 的非稳定重现错误 摘要 线上环境在 EhCache Replication 过程中出现 java.util.Concur ...
- gor实现线上HTTP流量复制压测引流
一.使用背景 gor 是一款go语言实现的简单的http流量复制工具,它的主要目的是使你的生产环境HTTP真实流量在测试环境和预发布环境重现.只需要在 代理例如nginx入口服务器上执行一个进程,就可 ...
- redis扫描特定keys脚本,可避免阻塞,不影响线上业务
#!/bin/sh ## 该脚本用来查询redis集群中,各个实例当中特定前缀的key,对应只需要修改redis的其中一个实例的 host和port## 脚本会自动识别出该集群的所有实例,并查出对应实 ...
- 线上服务宕机,码农试用期被毕业,原因竟是给MySQL加个字段
1. 问题:怎么给线上表加字段? 工作中最常遇到的问题,怎么给线上频繁使用的大表添加字段? 比如:给下面的用户表(user)添加年龄(age)字段. CREATE TABLE `user` ( `id ...
随机推荐
- Go的50度灰:开发者要注意的陷阱和常见错误
Go是一门简单有趣的语言,但与其他语言类似,它会有一些技巧...这些技巧的绝大部分并不是Go的缺陷造成的.如果你以前使用的是其他语言,那么这其中的有些错误就是很自然的陷阱.其它的是由错误的假设和缺少细 ...
- WinFrom Thread里面new出来的控件不显示
那本More Effective C# 好多天没看了..惭愧. 做个小笔记吧. 今天碰到一个问题,描述如题. 何解?其实很简单,因为Thread里面new出来的控件的Parent是null,然后他就不 ...
- SpringMVC学习(三)———— springmvc的数据校验的实现
一.什么是数据校验? 这个比较好理解,就是用来验证客户输入的数据是否合法,比如客户登录时,用户名不能为空,或者不能超出指定长度等要求,这就叫做数据校验. 数据校验分为客户端校验和服务端校验 客户端校验 ...
- Perl解除引用:从引用还原到数据对象
使用引用可以指向数据对象,这似乎很简单. @name1=qw(longshuai wugui); @name2=qw(xiaofang tuner); $ref_name=\@name1; push ...
- Go基础系列:流程控制结构
条件判断结构:if else 分支选择结构:switch case 循环结构:for break:退出for或switch结构(以及select) continue:进入下一次for迭代 虽然Go是类 ...
- [转]Node.js框架对比:Express/Koa/Hapi
本文转自:https://www.cnblogs.com/souvenir/p/6039990.html 本文翻译自: https://www.airpair.com/node.js/posts/no ...
- SVN 安装后右键出现点击鼠标右键弹出错误提示:CrashHandler initialization error
SVN 安装后右键出现点击鼠标右键弹出错误提示:CrashHandler initialization error 原因是目标文件夹中缺少SendRpt.exe文件 解决方案:找svn是好的的同事将b ...
- Contest2089 - 湖南多校对抗赛(2015.05.31) Swipe(csu1648)
Problem E: Swipe Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 100 Solved: 15[Submit][Status][Web ...
- 详解Parcel:快速,零配置web应用打包工具。
译者按: 新一代Web应用打包工具Parcel横空出世,快速.零配置的特点让人眼前一亮. 原文: Everything You Need To Know About Parcel: The Blazi ...
- crontab 配置文件
1.系统配置文件 etc/crontab 2.vim打开crontab 以上配置解释 1. 代表用bash去执行shell command line2.代表crontab 默认的环境变量3.cront ...