2012-01-01 43 views
5

我不明白:實習生字串誤解?

MSDN說

http://msdn.microsoft.com/en-us/library/system.string.intern.aspx

因此,文本字符串與特定值的實例 只存在於系統中一次。

例如,如果您分配相同的文字串幾個 變量,運行時獲取相同的參考,從實習生池的文字 字符串,並將其分配給每個變量。

這種行爲是默認的(沒有實習生)嗎?或通過使用Intern方法?

  • 如果它的默認值,那麼我爲什麼要使用實習生? (實例將會一次......)?

  • 如果它不是默認:如果我寫此行1000次:

    Console.WriteLine( 「LALALA」);

1)我會在內存中發生1000次「lalala」嗎? (不使用實習生...)

2)將「lalala」最終Gc'ed?

3)「lalala」是否已經實習?如果是這樣,爲什麼我需要從池中「獲得」它,而不是隻是再寫一次「lalala」?

林有點混淆。

回答

9

字符串字面自動實現(所以,如果您的代碼包含「lalala」1000次,則只有一個實例存在)。

這樣的字符串不會得到GC'd,並且任何時候它們被引用時,引用將是被禁止的。


string.Intern是有那些文字字符串 - 從用戶輸入說或從文件或數據庫中讀取和你知道會很經常重複,因此是值得一生實習的過程。

+0

那麼爲什麼我要使用'string.intern(「lalala」)'如果它自動從池中獲取?我可以使用「lalala」....請澄清... :) toda。 – 2012-01-01 08:10:04

+0

@RoyiNamir - 增加了一些關於'string.Intern'的信息。希望澄清一點。 – Oded 2012-01-01 08:14:09

+0

一如既往的謝謝你。第二部分爲我闡明瞭一些事情。 – 2012-01-01 08:23:58

5

實習是幕後發生的事情,所以你作爲程序員不必擔心。你通常不需要將任何東西放到池中,或者從池中獲取任何東西。像垃圾收集一樣:你永遠不必調用它,或者擔心它可能發生,或擔心它可能不會發生。 (那麼,在99.999%的情況下,其餘的0.001%是當你做的很奇怪的東西。)

編譯器負責實習源文件中包含的所有字符串文字,所以「lalala」將不需要做任何事情或對此事擁有任何控制權。每當你在你的程序中引用「lalala」時,編譯器都會確保從intern池中獲取它,而不需要你做任何事情,也沒有任何控制權。

實習生池包含一個或多或少固定數量的字符串,通常是一個非常小的大小(只有你的.exe總大小的一小部分),所以沒關係,他們永遠不會得到垃圾-集。


EDIT

實習串的目的是大大提高某些字符串操作的像等於執行時間()。 StringEquals()方法首先檢查字符串是否通過引用相等,這是非常快的;如果參考值相等,則立即返回true;如果引用不相等,並且字符串都被禁用,那麼它立即返回false,因爲它們不可能相等,因爲intern池中的所有字符串都不相同。如果以上都不成立,則通過字符串比較進行字符處理。 (實際上,它比這更復雜,因爲它也檢查字符串的hashcode,但讓我們在討論中保持簡單。)

因此,假設您正在讀取字符串s中的文件的標記,你有以下形式的switch語句:

switch(s) 
{ 
    case "cat": .... 
    case "dog": .... 
    case "tod": .... 
} 

字符串文字「貓」,「狗」,「TOD」都被扣留,但你是比較反對s他們的每一個,沒有被實習,所以你沒有收穫實習生池的好處。如果你在switch語句前實習s,那麼switch語句將進行的比較將會快得多。

當然,如果您的文件可能包含垃圾,那麼您不希望這樣做,因爲將大量隨機字符串加載到intern池中肯定會殺死程序的性能,並最終內存不足。

+0

'編譯器確保從intern池中獲取它... ...所以當我想明確使用string.intern? – 2012-01-01 08:27:01

+0

@Oded已經回答了這個問題。我會盡量在我的答案中給出一個例子。 – 2012-01-01 08:29:02

+0

我添加了一個例子。 – 2012-01-01 08:37:48