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

Долгосрочное: * один * из-за [интернирование строка] (http://broadcast.oreilly.com/2010/08/understanding-c-stringintern-m.html). Хотя каждый раз, когда вызывается 'GetStr', строка будет выделена до того, как она будет интернирована, а затем будет собрана мусор. –

+1

Я не думаю, что это должно было быть закрыто как дубликат. Указанный вопрос касается динамических строк. Этот вопрос связан с * постоянным строковым литералом *. '' OK ''будет переведен в код операции LDSTR' IL, который выталкивает ссылку на строку **, хранящуюся в метаданных **. Таким образом, будет выделена только одна строка. * Никакие временные строки не будут выделены * перед интернированием. –

+1

@BassamAlugili: Ну, 10 миллиардов ссылок в списке довольно много :-) –

ответ

9

Как будет создано много количества строк в памяти в случае выше коды

One. (Или на самом деле два, если вы включите "hmmmmmmmm")

Этот метод возвращает константа строковый литерал:

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

Она составлена ​​в нечто вроде следующего кода IL:

ldstr "OK" 
ret 

LDSTR opcode будет ссылаться на строковый литерал , сохраненный в метаданных, и код операции RET вернет t шляпа ссылка.

Это означает, что "OK" будет выделено только в метаданных. Все записи в списке будут ссылаться на этот экземпляр.

Обратите внимание, что строковые литералы интернированы по умолчанию. Таким образом, никакая «временная строка» не будет выделена перед интернированием, и поэтому сбор мусора не требуется.

+0

Я немного изменил код GetStr() и создал 1000000 плюс строки byte [] bytes = System.Text.Encoding.UTF8.GetBytes («ОК»); return System.Text.Encoding.UTF8.GetString (bytes); –

+2

@RoyaanKhan: Хорошо.Ну, тогда вы вынуждаете систему динамически выделять новую строку каждый раз. '" OK "' все равно будет ссылкой на строку, хранящуюся в метаданных. Однако 'UTF.GetString (bytes)' будет выделять новый экземпляр строки каждый раз при вызове. –

2

В вашем случае будет создано 2 строки, созданные вашим кодом: «ОК» и «hmmmmmmmm». Поскольку строка - неизменяемый тип, «ОК» будет создаваться только один раз, и каждый раз, когда она вам понадобится, строка будет просто указана.

+1

Тот факт, что 'string' является неизменяемым типом и тот факт, что он создан только один раз,« подключен », но это не« A подразумевает B », это больше« потому что A, мы (разработчики .NET) может сделать B, и мы сделали B ». – xanatos

+0

thanks @peer для меня этот совет - это ответ «Потому что строка неизменяемого типа будет создана один раз» +1 –

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); 
    } 
    } 
} 

------------ Console Output ------ ------------------

Как вы видите, список использует ту же ссылку на память для строки «Ok».

#225bf54 
#225bf54 
#225bf54 
#225bf54 
#225bf54 
#225bf54 
#225bf54 
#225bf54 
#225bf54 
#225bf54 
hmmmmmmmm 
Смежные вопросы