🚫 Ad Blocker Detected

Please disable your AD blocker to continue using this site. Ads help us keep the content free! please press keyboard F5 to refresh page after disabled AD blocker

請關閉廣告攔截器以繼續使用本網站。廣告有助於我們保證內容免費。謝謝! 關閉後請按 F5 刷新頁面

0%

那些年String.Format中的Boxing和UnBoxing

前言:

下面有兩個虛擬程式碼

1
2
3
4
5
int times = 30000000;
string s = string.Empty;

s = $"{times}";
s = $"{times.ToString()}";

請問下面這兩段程式碼有沒有差別?

1
2
s = $"{times}";
s = $"{times.ToString()}";

$""這個程式碼是string.Format()語法糖

如果知道差別的同學,恭喜你已經可以下課了

如果不知道差別也沒關係,讓我細細講述.

String.Format方法簽章

String.Format方法有一個重載方法,可以看到裡面吃參數是params object[]這可以讓我們傳進東西當作參數(他會在方法中呼叫ToString方法).

1
public static string Format(string format, params object[] args)

所以這段程式碼看起來應該是要一樣,但事實並非如此…

1
2
s = $"{times}";
s = $"{times.ToString()}";

$”{times}” vs $”{times.ToString()}”

在執行下面程式碼會發現兩段程式碼不管怎麼執行

執行時間$"{times}";永遠都會比$"{times.ToString()}";來的多

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
class Program
{
static void Main(string[] args)
{
int times = 30000000;
string s = string.Empty;
Stopwatch sw = new Stopwatch();
sw.Start();
for (int i = 0; i < times ; i++)
{
s = $"{times}";
}

sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);

sw.Restart();
for (int i = 0; i < times ; i++)
{
s = $"{times.ToString()}";
}
sw.Stop();
Console.WriteLine(sw.ElapsedMilliseconds);
Console.ReadKey();
}
}

執行時間如上圖

img

Source Code

這是為什麼呢??

原因出在Boxing和UnBoxing上…

Boxing 和 UnBoxing

在說BoxingUnBoxing之前

我們要了解.Net中的Refer TypeValue Type在記憶體存放上差別.

想了解Refer TypeValue Type的人,可以參考我之前寫文章 【C#】 參考類型 , 值類型 Equals方法 和 ==.

假如已經了解Refer TypeValue Type,在.Net中有分Stack記憶體區段和Heap記憶體區段.

  • Stack:存放Value Type(struct)資料
  • Heap:存放Refer Type資料

Boxing

因為在Boxing時我們會把Value Type資料複製一份資料到Refer Type記憶體中.

1
2
int i=20;
object o=(object)i;

上面程式碼大概會如下圖操作

int強制轉型為object 因為我們所有物件都是繼承於object物件

UnBoxing

至於UnBoxing動作就如下面程式碼

1
2
3
int i=20;
object o=(object)i;
int j=(int)o;

UnBoxing會將原本存在Heap的值,會把他搬回Stack並附值給J

o Object強轉成int在這個案例不會有問題,但如果是將o轉為char就會有問題

(解答)String.Format兩個範例 效能差異

如果有從頭看到尾小夥伴,相信應該可以了解到問什麼會有沒有.ToString會造成差異性了吧.

因為Boxing會造成系統無形中消耗,如果我們先把傳入Value Type資料轉成String再傳入就可以避免Boxing問題.

__此文作者__:Daniel Shih(石頭)
__此文地址__: https://isdaniel.github.io/stringformat-compare/
__版權聲明__:本博客所有文章除特別聲明外,均採用 CC BY-NC-SA 3.0 TW 許可協議。轉載請註明出處!

如果本文對您幫助很大,可街口支付斗內鼓勵石頭^^