91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

.Net中字符串不變性與相等判斷的特殊應用場景分析

發布時間:2022-04-21 17:07:29 來源:億速云 閱讀:124 作者:zzz 欄目:開發技術

這篇文章主要介紹了.Net中字符串不變性與相等判斷的特殊應用場景分析的相關知識,內容詳細易懂,操作簡單快捷,具有一定借鑒價值,相信大家閱讀完這篇.Net中字符串不變性與相等判斷的特殊應用場景分析文章都會有所收獲,下面我們一起來看看吧。

問題

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

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中字符串是享元模式的經典范例。字符串具有不變性。(至少在托管層,事實上可以在非托管層修改字符串的值),但你真的能回答對上面的問題么?

答案

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

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

如何在visual studio中查看變量的內存布局

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

  • 依次在調試模式下打開 調試 -> 窗口 -> 內存 -> 內存1(1~4均可) 打開內存對話框。

  • 在地址欄中輸入變量名即可。

字符串變量在內存中的布局

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

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的數(這里由于并沒有執行lock或Gethashcode操作,所以這里為0,感興趣的自行實驗.)

  • 98 d6 fc e5 fb 7f 00 00對象的MethodTable,根據類型而不同,對象的引用指向的位置。

  • 02 00 00 00 字符串長度,這里是2。

  • 31 00 32 00 字符串數組* char,注意都是小端模式。

拿以上s1 s2 o3 o4分別實驗可以發現他們的內存一模一樣,其中s1 s2直接就是同一塊內存地址,但剩下的內存地址都不一樣

比較與解答

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

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

    可能非有意的引用比較。

    既然是引用比較,內存地址都不一樣,肯定是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)

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

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

關于“.Net中字符串不變性與相等判斷的特殊應用場景分析”這篇文章的內容就介紹到這里,感謝各位的閱讀!相信大家對“.Net中字符串不變性與相等判斷的特殊應用場景分析”知識都有一定的了解,大家如果還想學習更多知識,歡迎關注億速云行業資訊頻道。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

工布江达县| 林甸县| 大姚县| 新乡市| 额敏县| 巴林左旗| 安塞县| 巴南区| 林甸县| 永昌县| 额敏县| 醴陵市| 吕梁市| 治县。| 布尔津县| 石狮市| 博湖县| 新野县| 天祝| 长寿区| 清水县| 安泽县| 包头市| 蛟河市| 朝阳市| 沁源县| 迁安市| 都兰县| 大姚县| 蕲春县| 黎川县| 佛教| 天全县| 长寿区| 连云港市| 屏东市| 丰城市| 黄龙县| 安徽省| 临高县| 万年县|