2015-02-24 148 views
4

我有一個關於字符串創建問題,在一個循環下面是一個代碼示例:字符串創建

static void Main(string[] args) 
    { 

     for (int i = 1; i <= 1000000; i++) 
     { 
      Add(GetStr()); 
     } 

     Console.WriteLine("hmmmmmmmm"); 
     Console.ReadLine(); 
    } 

    public static string GetStr() 
    { 
     return "OK";    
    } 

    public static void Add(string str) 
    { 
     list.Add(str); 
    } 

多少串的數量將存儲在上面的代碼的情況下創建???

+5

長期:* one *,由於[string interning](http://broadcast.oreilly.com/2010/08/understanding-c-stringintern-m.html)。儘管每次調用GetStr,字符串都會在被執行前被分配,然後被垃圾收集。 – 2015-02-24 06:59:08

+1

我不認爲這應該被重複關閉。引用的問題是關於動態字符串。這個問題是關於一個*常量字符串*。 'OK'將被轉換成'LDSTR' IL操作碼,它將存儲在元數據**中的字符串**的引用推送出去。所以只會分配一個字符串。 *在實習前不會有臨時字符串被分配*。 – 2015-02-24 07:25:04

+1

@BassamAlugili:列表中的100億引用非常多:-) – 2015-02-24 07:38:55

回答

9

如何串的許多數將在內存中的上述代碼

一個案例來創建。 (或者實際上是兩個,如果你有"hmmmmmmmm"

這個方法返回一個常量字符串字面

public static string GetStr() 
{ 
    return "OK";    
} 

它編譯成類似下面的IL代碼:

ldstr "OK" 
ret 

LDSTR操作碼將推送對存儲在元數據中的字符串文字的引用,並且RET操作碼將返回t帽子參考。

這意味着"OK"只會在元數據中分配一次。列表中的所有條目都將引用該實例。

請注意,字符串文字是默認實現的。因此,在被攔截之前不會分配「臨時字符串」,因此不需要垃圾回收。

+0

我改變了GetStr()代碼一點點,它創建了1000000加字符串 byte [] bytes = System.Text.Encoding.UTF8.GetBytes(「OK」); return System.Text.Encoding.UTF8.GetString(bytes); – 2015-02-24 07:49:27

+2

@RoyaanKhan:好的。那麼你強迫系統每次動態分配一個新的字符串。 '「確定」'仍然是對存儲在元數據中的字符串的引用。但是,每次調用時,'UTF.GetString(bytes)'都會分配一個新的字符串實例。 – 2015-02-24 07:51:06

2

在你的情況下,你的代碼會創建2個字符串:「OK」和「hmmmmmmmm」。因爲字符串是一個不可變的類型,所以「OK」只會被創建一次,並且每次需要它時,字符串都會被引用。

+1

字符串是一個不可變類型,它只創建一次的事實是「連接」的事實,但它不是「A意味着B」,它更多「因爲A,我們(.NET創建者)可以做B,我們做了B「。 – xanatos 2015-02-24 08:11:38

+0

謝謝@peer對我來說,這個技巧是答案「因爲字符串一個不可變的類型將被創建一次」+1 – 2015-02-24 08:36:48

5

我已經修改了你的代碼,這樣就可以看到字符串的內存addrese「OK」

using System; 

namespace ConsoleApplication4 
{ 
    using System.Collections.ObjectModel; 

    public class Program 
    { 
    static unsafe Collection<string> list = new Collection<string>(); 

    static unsafe void Main(string[] args) 
    { 
     for (int i = 1; i <= 10; i++) 
     { 
     Add(GetStr()); 
     } 

     foreach (var str in list) 
     { 
     fixed (char* ptr = str) 
     { 
      var addr = (IntPtr)ptr; 
      Console.WriteLine(addr.ToString("x")); 
     } 
     } 

     Console.WriteLine("hmmmmmmmm"); 
     Console.ReadLine(); 
    } 

    public unsafe static string GetStr() 
    { 
     return "OK"; 
    } 

    public unsafe static void Add(string str) 
    { 
     list.Add(str); 
    } 
    } 
} 

------------控制檯輸出------ ------------------

當您看到列表對字符串「Ok」使用相同的內存引用。

#225bf54 
#225bf54 
#225bf54 
#225bf54 
#225bf54 
#225bf54 
#225bf54 
#225bf54 
#225bf54 
#225bf54 
hmmmmmmmm