一次线上问题引发的对于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 = 2; value2 = 2; 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 = 2; int value2 = 2; 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 = 2; int ival = 2; 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 , 上面的结果又会有所不同,有兴趣的同学可以自己尝试一下。
上一篇: 将"a"标签当bunton使用
下一篇: MySQL 内置函数