2015-02-24 117 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