最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

詳解.Net中字符串不變性與相等判斷的特殊場景

 更新時間:2022年04月21日 15:08:42   作者:時風拖拉機  
本文主要介紹了.Net中字符串不變性與相等判斷的特殊場景,文中通過示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下

今天寫bug的時候幫同事解決了一個有趣的問題,可能很多人都會答錯。分享給大家。

問題

請看以下例子,并回答問題。

var s1 = "12";
var s2 = "12";

//序列化方式1
var o3 = Newtonsoft.Json.JsonConvert.DeserializeObject<string>(Newtonsoft.Json.JsonConvert.SerializeObject(s1));
//序列化方式2
MemoryStream stream = new MemoryStream();
System.Runtime.Serialization.Formatters.Binary.BinaryFormatter bf = new System.Runtime.Serialization.Formatters.Binary.BinaryFormatter();
bf.Serialize(stream, s1);
stream.Seek(0, SeekOrigin.Begin);
var o4 = bf.Deserialize(stream);

//====分割線===================================================

var e1 = object.ReferenceEquals(s1, s2);

var e2 = o4 == s1;

var e3 = s1.Equals(o4);

var e4 = o3 == o4;

Console.ReadKey();

請回答分割線后e1, e2, e3, e4 值為true還是false。

人人都知道在.Net中字符串是享元模式的經(jīng)典范例。字符串具有不變性。(至少在托管層,事實上可以在非托管層修改字符串的值),但你真的能回答對上面的問題么?

答案

e1 = true;
e2 = false;
e3 = true;
e4 = false;

要了解這個問題首先可以看下字符串在內(nèi)存中的布局。

如何在visual studio中查看變量的內(nèi)存布局

在VS中可以非常方便的查看托管或非托管變量的內(nèi)存值。方法如下。

  • 依次在調試模式下打開 調試 -> 窗口 -> 內(nèi)存 -> 內(nèi)存1(1~4均可) 打開內(nèi)存對話框。
  • 在地址欄中輸入變量名即可。

字符串變量在內(nèi)存中的布局

在.Net中字符串是以UTF-16格式在內(nèi)存中保存的。在本例中s1的內(nèi)存如下。

00 00 00 00 00 00 00 00 98 d6 fc e5 fb 7f 00 00 02 00 00 00 31 00 32 00

這里可能與你拿到的結果不一樣。你可能并沒有前8位0x00,因為我把對象頭帶上了。下面依次解釋各段含義。

  • 00 00 00 00 00 00 00 00 最開始的8比特是對象頭。其中,在64位下,高4位為0,低4位為一個不為0的數(shù)(這里由于并沒有執(zhí)行l(wèi)ock或Gethashcode操作,所以這里為0,感興趣的自行實驗.)
  • 98 d6 fc e5 fb 7f 00 00對象的MethodTable,根據(jù)類型而不同,對象的引用指向的位置。
  • 02 00 00 00 字符串長度,這里是2。
  • 31 00 32 00 字符串數(shù)組* char,注意都是小端模式。

拿以上s1 s2 o3 o4分別實驗可以發(fā)現(xiàn)他們的內(nèi)存一模一樣,其中s1 s2直接就是同一塊內(nèi)存地址,但剩下的內(nèi)存地址都不一樣。

比較與解答

  • e1 = true; 通過內(nèi)存看合情合理,畢竟都同一塊內(nèi)存了。

  • e2 = false; 這里如果用的VS的版本比較高的話,也能看出來。因為這里VS會提示:

    可能非有意的引用比較。

    既然是引用比較,內(nèi)存地址都不一樣,肯定是false了。但是如果vs版本不高的話則迷惑性就較大了,其實這里做的是ReferenceEquals的比較。

  • e3 = true; 這里問題出在.Net代碼里。字符串類型Equals方法被重載了。

        // Determines whether two strings match.
        public override bool Equals([NotNullWhen(true)] object? obj)
        {
            if (object.ReferenceEquals(this, obj))
                return true;

            if (!(obj is string str))
                return false;

            if (this.Length != str.Length)
                return false;

            return EqualsHelper(this, str);
        }

EqualsHelper方法最終則調用如下。(在.Net 6下)

        // Optimized byte-based SequenceEquals. The "length" parameter for this one is declared a nuint rather than int as we also use it for types other than byte
        // where the length can exceed 2Gb once scaled by sizeof(T).
        public static unsafe bool SequenceEqual(ref byte first, ref byte second, nuint length)

由于實現(xiàn)過于復雜(.Net framework 4.5.2下則較簡單,直接按長度比較char,有興趣的自行查閱),這里就不貼具體實現(xiàn)了。我們很容易看出這里比較的目的是比較兩段內(nèi)存是否相等,顯然為true。

  • e4 = false;這里是為了比較不同序列化方式的影響,和e2類似,結果顯然是false。

結論

雖然.Net中字符串是享元模式創(chuàng)建的,但并不能保證同一字符串在內(nèi)存里只有一份。比如序列化情況等例外情況。如果讀者知道其他情況也可以告訴我,提前說聲感謝

到此這篇關于詳解.Net中字符串不變性與相等判斷的特殊場景的文章就介紹到這了,更多相關.Net中字符串不變性與相等判斷內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!

相關文章

  • asp.net Repeater之非常好的數(shù)據(jù)分頁

    asp.net Repeater之非常好的數(shù)據(jù)分頁

    asp.net Repeater之非常好的數(shù)據(jù)分頁實現(xiàn)代碼。
    2009-07-07
  • .Net Core微信服務商二次進件的開發(fā)

    .Net Core微信服務商二次進件的開發(fā)

    這篇文章主要介紹了.Net Core微信服務商二次進件的開發(fā),包括服務商證書獲取方法及查詢進件狀態(tài)的詳細代碼,本文給大家介紹的非常詳細,需要的朋友可以參考下
    2021-10-10
  • ASP.NET預定義模板介紹

    ASP.NET預定義模板介紹

    在調用這些方法的時候,如果我們指定了一個具體的通過分部View定義的模板,或者對應的ModelMetadata的TemplateHint屬性具有一個模板名稱,會自動采用該模板來生成最終的HTML,需要了解這方面內(nèi)容的朋友可以參考一下
    2015-10-10
  • asp.net6?blazor?文件上傳功能

    asp.net6?blazor?文件上傳功能

    這篇文章主要介紹了asp.net6?blazor?文件上傳,我們今天的所有內(nèi)容,都要依賴這個接口,因為它可以把流直接傳到c#中,這樣我們就可以做很多的騷操作了,需要的朋友可以參考下
    2022-05-05
  • asp.net實現(xiàn)的DES加密解密操作示例

    asp.net實現(xiàn)的DES加密解密操作示例

    這篇文章主要介紹了asp.net實現(xiàn)的DES加密解密操作,結合具體實例形式分析了asp.net實現(xiàn)DES加密與解密算法的實現(xiàn)技巧,需要的朋友可以參考下
    2017-07-07
  • ASP.NET Core AutoWrapper 自定義響應輸出實現(xiàn)

    ASP.NET Core AutoWrapper 自定義響應輸出實現(xiàn)

    這篇文章主要介紹了ASP.NET Core AutoWrapper 自定義響應輸出實現(xiàn),文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-08-08
  • ASP.NET Core中如何利用多種方式給Action傳參

    ASP.NET Core中如何利用多種方式給Action傳參

    這篇文章主要給大家介紹了關于ASP.NET Core中如何利用多種方式給Action傳參的相關資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧
    2020-12-12
  • ASP.NET導出數(shù)據(jù)到Excel的實現(xiàn)方法

    ASP.NET導出數(shù)據(jù)到Excel的實現(xiàn)方法

    在做asp.net程序時涉及到數(shù)據(jù)顯示的時候多數(shù)會要求打印,而網(wǎng)頁上的打印格式往往又不能滿足需求,經(jīng)常用的方法就是導入到Excel以后再進行打印。(仿佛這已經(jīng)是老生常談)今天在網(wǎng)上搜了一段打印的代碼,覺得不錯,需要打印的朋友可以看看。
    2013-07-07
  • .NET Core中如何實現(xiàn)或使用對象池?

    .NET Core中如何實現(xiàn)或使用對象池?

    什么是對象池?簡單來說它就是一種為對象提供可復用性能力的軟件設計思路,對象池就是通過“借”和“還”這樣兩個動作來保證對象可以被重復使用,這篇文章主要給大家介紹了關于.NET Core中如何實現(xiàn)或使用對象池的相關資料,需要的朋友可以參考下
    2021-07-07
  • C# 事件的設計與使用深入理解

    C# 事件的設計與使用深入理解

    事件是用于通知其他對象發(fā)生了本對象發(fā)生了特定的事情的類型成員;事件是.NET類型成員中相對較為難以理解和實踐的一個成員,因為事件的定義不是繼承自基礎的數(shù)據(jù)類型,而是對委托(delegate)的封裝。所以,在了解事件之前,你需要先了解一點委托
    2012-12-12

最新評論

界首市| 偃师市| 秦皇岛市| 陕西省| 陈巴尔虎旗| 宽甸| 满城县| 原平市| 通辽市| 长春市| 玛多县| 丰原市| 五华县| 莱芜市| 河津市| 庆阳市| 那曲县| 合江县| 宝应县| 昌吉市| 华亭县| 大悟县| 铁岭市| 重庆市| 肇州县| 甘孜| 洪江市| 和龙市| 阜阳市| 平昌县| 绩溪县| 乌鲁木齐市| 驻马店市| 本溪| 抚顺县| 商洛市| 绍兴县| 卓尼县| 安达市| 永川市| 阿合奇县|