公司的程序員小高在寫代碼的時(shí)候遇到一個(gè)問題,問題也很簡(jiǎn)單,那就是小高在寫一個(gè)參數(shù)配置的頁(yè)面的時(shí)候,若界面參數(shù)發(fā)生了改變,那么需要彈窗提醒用戶是否保存參數(shù),可這個(gè)參數(shù)配置頁(yè)面有幾百個(gè)參數(shù)需要配置,如果要對(duì)所有參數(shù)與數(shù)據(jù)庫(kù)的參數(shù)進(jìn)行逐一比對(duì),那可是個(gè)大工程,小高嘗試了很多方法,結(jié)果都沒有達(dá)到預(yù)期的效果。
小高寫的參數(shù)配置頁(yè)面的原本操作邏輯是編輯完頁(yè)面數(shù)據(jù)后,點(diǎn)擊頁(yè)面的“返回”按鈕,不管頁(yè)面有沒有發(fā)生改變,均彈窗提示用戶是否保存配置的參數(shù)!
當(dāng)我看到小高的做法以后,我覺得小高開始的做法在用戶體驗(yàn)上有點(diǎn)問題,因?yàn)橛脩魜磉@個(gè)界面不一定就是要改配置參數(shù),有可能就是看一眼,但每次返回時(shí)都要被彈窗詢問是否保存數(shù)據(jù),從用戶角度,這樣的軟件使用體驗(yàn)肯定是有問題的。
所以,我跟小高說,不要每次都彈窗,而是當(dāng)配置發(fā)生變化時(shí)再?gòu)棿埃⌒「哂X得我說的也有道理,但是,他隨之拋給了我一個(gè)問題。
據(jù)小高說,他也不是沒想過按照我的想法去做,但是,如果一個(gè)參數(shù)一個(gè)參數(shù)去比對(duì),那么光驗(yàn)證參數(shù)是否改動(dòng)這塊的代碼就有成百上千行,這么寫不光累,代碼可能還不利于維護(hù)。
我問他:“用Equals不行嗎?”
小高跟我說,Equals他試過,即使兩個(gè)對(duì)象的內(nèi)容完全相等,使用Equals的比對(duì)結(jié)果仍然是False!
這讓我有點(diǎn)尷尬了,因?yàn)槲冶凰@么一說,我才想起來,我似乎從來沒有用過Equals!
這得說到我倆的技術(shù)背景,都是C#!
在C#中大多數(shù)情況下,我們都只會(huì)使用“==”號(hào)來判斷兩個(gè)對(duì)象的值是否相等,之所以不常使用Equals,那是因?yàn)椤?=”和Equals大部分情況下作用是一樣的,對(duì)于值類型而言(比如1、2、3、4、5),因?yàn)橹殿愋投际谴鎯?chǔ)在棧上,因此“==”和Equals判斷的都是兩個(gè)值類型的值是否相等。而對(duì)于引用類型而言,使用“==”就是比對(duì)兩個(gè)對(duì)象之間的棧地址是否相等,使用Equals就是比對(duì)兩個(gè)對(duì)象之間的堆地址是否相等,也就是Equals實(shí)際上比對(duì)的是兩個(gè)對(duì)象是否是對(duì)同一個(gè)對(duì)象的引用。
因此,假設(shè)有一個(gè)對(duì)象A,此時(shí),如果給B賦值,B=A的情況下,使用Equals來比對(duì),那么A和B是能劃上等號(hào)的。
再回到開始的需求,小高在參數(shù)配置頁(yè)面點(diǎn)擊“返回”時(shí)已經(jīng)將頁(yè)面上的數(shù)據(jù)重新new了一個(gè)對(duì)象,這里我們把這個(gè)對(duì)象看作B,而每次保存完成以后,需要對(duì)原本的參數(shù)對(duì)象進(jìn)行重新賦值,這個(gè)原本的對(duì)象我們看作A,因此B對(duì)象(引用類型)的地址和A對(duì)象所引用的地址不管對(duì)于“==”來說還是Equals來說,其實(shí)比較得都是地址而不是內(nèi)容。因此,這么比的話永遠(yuǎn)是False。
此時(shí),小高找了一堆第三方庫(kù),第三方庫(kù)其實(shí)能夠達(dá)到比對(duì)內(nèi)容的目的,但是,我把小高的找到的庫(kù)逐一看了一遍,無奈本人有強(qiáng)迫癥,非MIT開源協(xié)議的第三方庫(kù),我認(rèn)為都有商業(yè)風(fēng)險(xiǎn),于是,小高找的庫(kù)全軍覆沒!
最后,實(shí)在沒辦法,有問題,找百度,我找到了一個(gè)比較經(jīng)濟(jì)實(shí)惠又沒有商業(yè)風(fēng)險(xiǎn)的做法,那就是將兩個(gè)需要比對(duì)的對(duì)象直接序列化成為Json字符串,然后拿兩個(gè)Json字符串進(jìn)行比對(duì)!
這里要說到C#中的字符串(String)類型的特殊之處了!
眾所周知,字符串這個(gè)類型在大部分編程語言里,它都是引用類型,在C#里面也是,但是,特殊的地方在于,當(dāng)兩個(gè)字符串在進(jìn)行比對(duì)的時(shí)候,其實(shí)比對(duì)的是字符串的值!(大家不用翻論文,總之就是這個(gè)意思)
所以,只要兩個(gè)Json字符串是一模一樣的,那么不管使用“==”還是使用Equals,得到的結(jié)果均是True,當(dāng)然了,我還是喜歡使用“==”來比對(duì)!
結(jié)語
到了這里,小高是算是解決了他所需要解決的問題,但是,我其實(shí)還是覺得不夠完美,可能最佳的解決方案是通過反射兩個(gè)對(duì)象里面的屬性,然后通過比對(duì)屬性的值來判斷兩個(gè)對(duì)象的內(nèi)容是否相等,但是,這無疑會(huì)將問題變得更加復(fù)雜,舉個(gè)很簡(jiǎn)單的例子,假設(shè)一個(gè)對(duì)象中包含著另一個(gè)對(duì)象,而另一個(gè)對(duì)象又包含著另外一個(gè)對(duì)象……,而每個(gè)對(duì)象里面的屬性的數(shù)據(jù)類型可能還不一樣,需要逐一判斷,這無疑增加了代碼的復(fù)雜性,這種偏底層的東西,我是不愿意碰的!
況且,這也背離了我想要使用簡(jiǎn)單的方法解決問題的初衷!
但是,我說得不完美,其實(shí)還包含了另外一層意思,因?yàn)槲遗聦?duì)象轉(zhuǎn)換成Json以后,Json的每一個(gè)屬性的位置會(huì)在最終轉(zhuǎn)換出來的字符串Json中發(fā)生變化,這樣兩個(gè)字符串就變得不相等了。
但是,我嘗試了很多次,發(fā)現(xiàn)無論我怎么轉(zhuǎn)換,最終兩個(gè)內(nèi)容完全一樣的不同對(duì)象,轉(zhuǎn)換出來的Json串都是一模一樣的。
所以,您認(rèn)為將對(duì)象轉(zhuǎn)換成Json后進(jìn)行比對(duì)這個(gè)方法靠譜嗎?有沒有其他風(fēng)險(xiǎn)呢?
特別聲明:以上內(nèi)容(如有圖片或視頻亦包括在內(nèi))為自媒體平臺(tái)“網(wǎng)易號(hào)”用戶上傳并發(fā)布,本平臺(tái)僅提供信息存儲(chǔ)服務(wù)。
Notice: The content above (including the pictures and videos if any) is uploaded and posted by a user of NetEase Hao, which is a social media platform and only provides information storage services.